digitemp-3.6.0+dfsg1/0000755000175000017500000000000011743440264013033 5ustar ryanryandigitemp-3.6.0+dfsg1/digitemp-cflags.patch0000644000175000017500000000056411055616506017120 0ustar ryanryan--- digitemp-3.6.0/Makefile 2008-08-28 14:43:35.000000000 -0700 +++ digitemp-3.6.0/Makefile.rpm 2008-08-28 14:46:06.000000000 -0700 @@ -12,7 +12,7 @@ VERSION = 3.6.0 CC = gcc -CFLAGS = -I./src -I./userial -O2 -Wall # -g +CFLAGS = -I./src -I./userial $(RPM_OPT_FLAGS) OBJS = src/digitemp.o src/device_name.o src/ds2438.o HDRS = src/digitemp.h src/device_name.h digitemp-3.6.0+dfsg1/COPYRIGHT0000644000175000017500000000161111055345173014324 0ustar ryanryan DigiTemp v3.6.0 Dallas Semiconductor one-wire temperature sensor interface http://www.digitemp.com Copyright (c) 1996-2008 by Brian C. Lane http://www.brianlane.com 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA digitemp-3.6.0+dfsg1/contrib/0000755000175000017500000000000010632073746014476 5ustar ryanryandigitemp-3.6.0+dfsg1/contrib/digitemp-freebsd.patch0000644000175000017500000000440510632073746020734 0ustar ryanryandiff -urN digitemp-3.2.0-org/userial/cnt1d.c digitemp-3.2.0/userial/cnt1d.c --- digitemp-3.2.0-org/userial/cnt1d.c Thu May 22 03:50:21 2003 +++ digitemp-3.2.0/userial/cnt1d.c Sat Oct 25 18:17:41 2003 @@ -30,6 +30,8 @@ // // #include "ownet.h" +#include +typedef unsigned long ulong; // external One Wire functions from nework layer extern SMALLINT owAccess(int); diff -urN digitemp-3.2.0-org/userial/crcutil.c digitemp-3.2.0/userial/crcutil.c --- digitemp-3.2.0-org/userial/crcutil.c Thu May 22 03:50:20 2003 +++ digitemp-3.2.0/userial/crcutil.c Sat Oct 25 18:17:41 2003 @@ -29,6 +29,7 @@ // Include files #include "ownet.h" +#include // Local subroutines void setcrc16(int,ushort); diff -urN digitemp-3.2.0-org/userial/ds9097/owtran.c digitemp-3.2.0/userial/ds9097/owtran.c --- digitemp-3.2.0-org/userial/ds9097/owtran.c Thu May 22 03:50:19 2003 +++ digitemp-3.2.0/userial/ds9097/owtran.c Sat Oct 25 18:17:41 2003 @@ -34,6 +34,7 @@ // #include "ownet.h" +#include //-------------------------------------------------------------------------- // The 'owBlock' transfers a block of data to and from the diff -urN digitemp-3.2.0-org/userial/ds9097u/owtrnu.c digitemp-3.2.0/userial/ds9097u/owtrnu.c --- digitemp-3.2.0-org/userial/ds9097u/owtrnu.c Thu May 22 03:50:20 2003 +++ digitemp-3.2.0/userial/ds9097u/owtrnu.c Sat Oct 25 18:17:41 2003 @@ -41,6 +41,7 @@ #include "ownet.h" #include "ds2480.h" +#include // external functions defined in owllu.c extern SMALLINT owTouchReset(int); diff -urN digitemp-3.2.0-org/userial/ioutil.c digitemp-3.2.0/userial/ioutil.c --- digitemp-3.2.0-org/userial/ioutil.c Thu May 22 03:50:21 2003 +++ digitemp-3.2.0/userial/ioutil.c Sat Oct 25 18:17:41 2003 @@ -37,6 +37,8 @@ #include #include "ownet.h" +typedef unsigned long ulong; + #ifdef __MC68K__ #include #include diff -urN digitemp-3.2.0-org/userial/owproto.h digitemp-3.2.0/userial/owproto.h --- digitemp-3.2.0-org/userial/owproto.h Thu May 22 03:50:21 2003 +++ digitemp-3.2.0/userial/owproto.h Sat Oct 25 18:17:41 2003 @@ -29,7 +29,7 @@ char *owGetErrorMsg(int); #endif - +typedef unsigned long ulong; /* From ioutil.c */ int EnterString(char *, char *, int, int); digitemp-3.6.0+dfsg1/contrib/libusb.patch.txt0000644000175000017500000000617610632073746017627 0ustar ryanryan--------------070507070300030101020103 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit I've successfully used the driver found in main PDK archive (owpd300b2.zip) under generic library using usblnk.c and usbses.lnk. This driver in turn uses libusb library found on the internet. I've found libusb v0.1.7, which contained a small bug in linux.c file. The fixed routine is below. int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout) { struct usb_bulktransfer bulk; int ret, retrieved = 0, requested; /* Ensure the endpoint address is correct */ ep |= USB_ENDPOINT_IN; do { bulk.ep = ep; requested = size - retrieved; if (requested > MAX_READ_WRITE) requested = MAX_READ_WRITE; bulk.len = requested; bulk.timeout = timeout; bulk.data = (unsigned char *)bytes + retrieved; ret = ioctl(dev->fd, IOCTL_USB_BULK, &bulk); if (ret < 0) USB_ERROR_STR(ret, "error reading from bulk endpoint 0x%x: %s", ep, strerror(errno)); retrieved += ret; } while (ret > 0 && retrieved < size); /* Yefim: && ret == requested */ return retrieved; } Best regards, Mike. bcl wrote: >On Wed, Jul 23, 2003 at 05:57:50AM -0400, Paul Alfille wrote: > > >>Has anyone written a driver for the DS9490 USB master for Linux? >> >>I will try if it hasn't been done, but it's not my area of expertise. >> >> >> > >Not yet (to my knowledge), although I am trying to make the time to get >started on the project. > >Brian > > > --------------070507070300030101020103 Content-Type: text/html; charset=us-ascii Content-Transfer-Encoding: 7bit I've successfully used the driver found in main PDK archive (owpd300b2.zip) under generic library using usblnk.c and usbses.lnk. This driver in turn uses libusb library found on the internet. I've found libusb v0.1.7, which contained a small bug in linux.c file. The fixed routine is below. int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout) { struct usb_bulktransfer bulk; int ret, retrieved = 0, requested; /* Ensure the endpoint address is correct */ ep |= USB_ENDPOINT_IN; do { bulk.ep = ep; requested = size - retrieved; if (requested > MAX_READ_WRITE) requested = MAX_READ_WRITE; bulk.len = requested; bulk.timeout = timeout; bulk.data = (unsigned char *)bytes + retrieved; ret = ioctl(dev->fd, IOCTL_USB_BULK, &bulk); if (ret < 0) USB_ERROR_STR(ret, "error reading from bulk endpoint 0x%x: %s", ep, strerror(errno)); retrieved += ret; } while (ret > 0 && retrieved < size); /* Yefim: && ret == requested */ return retrieved; } Best regards, Mike. bcl wrote: >On Wed, Jul 23, 2003 at 05:57:50AM -0400, Paul Alfille wrote: > > >>Has anyone written a driver for the DS9490 USB master for Linux? >> >>I will try if it hasn't been done, but it's not my area of expertise. >> >> >> > >Not yet (to my knowledge), although I am trying to make the time to get >started on the project. > >Brian > > > digitemp-3.6.0+dfsg1/userial/0000755000175000017500000000000011055620247014474 5ustar ryanryandigitemp-3.6.0+dfsg1/userial/swt1f.c0000644000175000017500000002622210632073746015716 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //-------------------------------------------------------------------------- // // swt1f.c - Does commands on the DS2409 device // // version 2.00-digitemp // Fixed problem of not finding more than 1 device on main branch by // changing owBranchNext to use Smart Main instead of Main On command // // version 2.00 // - future version will have branch of a branch searches // // Include files #include #include "ownet.h" // external One Wire functions from nework layer extern SMALLINT owAccess(int); extern SMALLINT owFirst(int,SMALLINT,SMALLINT); extern SMALLINT owNext(int,SMALLINT,SMALLINT); extern void owSerialNum(int,uchar *,SMALLINT); // external One Wire functions from transaction layer extern SMALLINT owBlock(int,SMALLINT,uchar *,SMALLINT); // Local subroutines int SetSwitch1F(int,uchar *,int,int,uchar *,int); int SwitchStateToString1F(int, char *); int FindBranchDevice(int,uchar *,uchar BranchSN[][8],int,int); int owBranchFirst(int,uchar *,int,int); int owBranchNext(int,uchar *,int,int); //---------------------------------------------------------------------- // SUBROUTINE - SetSwitch1F // // This routine sets the main and auxilary on and off for DS2409. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'SerialNum' - Serial Number of DS2409 to set the switch state // 'Swtch' - '0' Sets Main and Auxilary off // '1' Sets Main on // '2' Sets Auxilary on // '3' Read Status Info Byte // '4' Smart On Main // 'NumExtra' - The number of extra bytes for a command. // 'InfoByte' - Returns the info byte and other information depending // on the command. The InfoByte size changes depending on // the NumExtra which is buffer length * (NumExtra + 1) // 'rst' - True then reset the search for devices // False don't reset search // // Returns: TRUE(1) State of DS2409 set and verified // FALSE(0) could not set the DS2409, perhaps device is not // in contact // int SetSwitch1F(int portnum, uchar *SerialNum, int Swtch, int NumExtra, uchar *InfoByte, int rst) { int send_cnt,i,cmd; uchar send_block[50]; if(owAccess(portnum)) { send_cnt = 0; // add the match command send_block[send_cnt++] = 0x55; for (i = 0; i < 8; i++) send_block[send_cnt++] = SerialNum[i]; // the command switch(Swtch) { case 0: // All lines off send_block[send_cnt++] = 0x66; cmd = 0x66; break; case 1: // Direct on Main send_block[send_cnt++] = 0xA5; cmd = 0xA5; break; case 2: // Smart on Auxilary send_block[send_cnt++] = 0x33; cmd = 0x33; break; case 3: // Status Read/Write send_block[send_cnt++] = 0x5A; cmd = 0x5A; // bytes 0-2: don't care // bytes 3-4: write control 0 to change status // byte 5: 0 = auto-control, 1 = manual mode // byte 6: 0 = main, 1 = auxiliary // byte 7: value to be written to control output, manual mode only // 0x00 default value *InfoByte = 0x00; send_block[send_cnt++] = *InfoByte; break; case 4: // Smart on Main send_block[send_cnt++] = 0xCC; cmd = 0xCC; break; default: return FALSE; } // extra bytes and confirmation for(i=0; i<=NumExtra; i++) send_block[send_cnt++] = 0xFF; // send the command string if(owBlock(portnum,rst,send_block,send_cnt)) { // returned information for the info byte and command for(i=0; i<=NumExtra; i++) *(InfoByte+(NumExtra-i)) = send_block[send_cnt - (i+2)]; // Set because for the read/write command the confirmation // byte is the same as the status byte if (Swtch == 3) cmd = send_block[send_cnt - 2]; if (send_block[send_cnt - 1] == cmd) return TRUE; } } return FALSE; } //---------------------------------------------------------------------- // SUBROUTINE = FindBranchDevices // // This routine will find all the branches on a certain DS2409 device and // will return the serial numbers down that branch // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'Branch[8]' - The serial number of the branch to look down // 'BranchSN[][8]' - The list of serial numbers on the branch // 'MAXDEVICES' - The Max devices on the branch // 'MainBr' - True to search down the main branch, False for Aux. // // Returns: Returns the number of devices found on the branch // int FindBranchDevice(int portnum, uchar Branch[8], uchar BranchSN[][8], int MAXDEVICES, int MainBr) { int NumDevices = 0; short result; result = owBranchFirst(portnum, &Branch[0], FALSE, MainBr); while(result) { owSerialNum(portnum,BranchSN[NumDevices], TRUE); NumDevices++; result = owBranchNext(portnum, &Branch[0], FALSE, MainBr); } return NumDevices; } //---------------------------------------------------------------------- // SUBROUTINE - owBranchFirst // // This routine is used like owFirst but for devices on a branch. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'BrSN' - This is the DS2409 device branch // 'AlarmD' - True or False, to do Alarm search or false for regular search // 'FirMain' - True then search main branch, False search Aux. branch // // 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 1-Wire Net. // int owBranchFirst(int portnum, uchar BrSN[8], int AlarmD, int FirMain) { int smart_main = 4; int smart_aux = 2; int numextra = 2; uchar extra[3]; if(FirMain) { if(SetSwitch1F(portnum, &BrSN[0], smart_main, numextra, extra, TRUE)) if(extra[2] != 0xFF) return owFirst(portnum,FALSE, AlarmD); } else { if(SetSwitch1F(portnum, &BrSN[0], smart_aux, numextra, extra, TRUE)) if(extra[2] != 0xFF) return owFirst(portnum,FALSE, AlarmD); } return FALSE; } //---------------------------------------------------------------------- // SUBROUTINE - owBranchNext // // This routine is used like owFirst but for devices on a branch. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'BrSN' - This is the DS2409 device branch // 'AlarmD' - True or False, to do Alarm search or false for regular search // 'NextMain' - True then search main branch, False search Aux. branch // // 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 1-Wire Net. // int owBranchNext(int portnum, uchar BrSN[8], int AlarmD, int NextMain) { int smart_main = 4; /* Was 1, Main On [bcl - 01132002 */ int smart_aux = 2; int numextra = 2; uchar extra[3]; if(NextMain) { if(SetSwitch1F(portnum, &BrSN[0], smart_main, numextra, extra, TRUE)) return owNext(portnum,FALSE, AlarmD); } else { if(SetSwitch1F(portnum, &BrSN[0], smart_aux, numextra, extra, TRUE)) return owNext(portnum,FALSE, AlarmD); } return FALSE; } //---------------------------------------------------------------------- // SUBROUTINE - SwitchStateToString // // This routine uses the info byte to return a string with all the data. // // 'infobyte' - This is the information byte data from the hardware. // 'outstr' - This will be the output string. It gets set in the // the procedure. // // Returns - Returns the number of characters in the string // int SwitchStateToString1F(int infobyte, char *outstr) { int cnt = 0; if(infobyte & 0x80) { cnt += sprintf(outstr+cnt, "%s", "Manual mode\n"); if(infobyte & 0x40) cnt += sprintf(outstr+cnt, "%s", "Output transistor on\n"); else cnt += sprintf(outstr+cnt, "%s", "Output transistor off\n"); } else { cnt += sprintf(outstr+cnt, "%s", "Auto-control mode\n"); if(infobyte & 0x40) cnt += sprintf(outstr+cnt, "%s", "Output association with Auxillary\n"); else cnt += sprintf(outstr+cnt, "%s", "Output association with Main\n"); } if(infobyte & 0x20) cnt += sprintf(outstr+cnt, "%s", "Negative edge sensed since inactive on Main\n"); else cnt += sprintf(outstr+cnt, "%s", "No event on Main\n"); if(infobyte & 0x10) cnt += sprintf(outstr+cnt, "%s", "Negative edge sensed since inactive on Aux.\n"); else cnt += sprintf(outstr+cnt, "%s", "No event on Aux.\n"); if(infobyte & 0x08) cnt += sprintf(outstr+cnt, "%s", "Voltage High on Aux. output\n"); else cnt += sprintf(outstr+cnt, "%s", "Voltage Low on Aux. output\n"); if(infobyte & 0x04) cnt += sprintf(outstr+cnt, "%s", "Inactive status of Aux. output\n"); else cnt += sprintf(outstr+cnt, "%s", "Active status of Aux. output\n"); if(infobyte & 0x02) cnt += sprintf(outstr+cnt, "%s", "Voltage High on Main output\n"); else cnt += sprintf(outstr+cnt, "%s", "Voltage Low on Main output\n"); if(infobyte & 0x01) cnt += sprintf(outstr+cnt, "%s", "Inactive status on Main output\n"); else cnt += sprintf(outstr+cnt, "%s", "Active status on Main output\n"); return cnt; } digitemp-3.6.0+dfsg1/userial/thermo21.c0000644000175000017500000013201010632073746016304 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // thermo21.c - Thermochron iButton utility functions // // Version: 2.00 // // History: // 1.03 -> 2.00 Reorganization of Public Domain Kit // Convert to global CRC utility functions // Y2K fix. #include "ownet.h" #include "thermo21.h" #include #include // Include files for the Palm and Visor #ifdef __MC68K__ #include #include #else #include #endif // structure to hold each state in the StateMachine typedef struct { int Step; char StepDescription[50]; } ThermoScript; // step constants enum { ST_SETUP=0, ST_READ_STATUS, ST_READ_ALARM, ST_READ_HIST, ST_READ_LOG, ST_CLEAR_MEM, ST_CLEAR_VERIFY, ST_WRITE_TIME, ST_WRITE_CONTROL, ST_WRITE_RATE, ST_FINISH, ST_GET_SESSION, ST_FIND_THERMO, ST_REL_SESSION, ST_READ_PAGES, ST_WRITE_MEM, ST_CLEAR_SETUP }; // status contants enum { STATUS_STEP_COMPLETE, STATUS_COMPLETE, STATUS_INPROGRESS, STATUS_ERROR_HALT, STATUS_ERROR_TRANSIENT }; // download steps static ThermoScript Download[] = {{ ST_READ_STATUS, "Setup to read the mission status"}, { ST_READ_PAGES, "Read the status page"}, { ST_READ_ALARM, "Setup to read alarm pages"}, { ST_READ_PAGES, "Read the alarm pages"}, { ST_READ_HIST, "Setup to read histogram pages"}, { ST_READ_PAGES, "Read the histogram pages"}, { ST_READ_LOG, "Setup to read log pages"}, { ST_READ_PAGES, "Read the log pages"}, { ST_FINISH, "Finished"}}; // read status only steps static ThermoScript GetStatus[] = {{ ST_READ_STATUS, "Setup to read the mission status"}, { ST_READ_PAGES, "Read the status page"}, { ST_FINISH, "Finished"}}; // mission steps (assume already did StatusThermo) static ThermoScript Mission[] = {{ ST_CLEAR_SETUP, "Setup clear memory"}, { ST_WRITE_MEM, "Write clear memory bit"}, { ST_CLEAR_MEM, "Clear the memory"}, { ST_READ_STATUS, "Setup to read the mission status"}, { ST_READ_PAGES, "Read the status page"}, { ST_CLEAR_VERIFY, "Verify memory is clear"}, { ST_WRITE_TIME, "Setup to write the real time clock"}, { ST_WRITE_MEM, "Write the real time clock"}, { ST_WRITE_CONTROL,"Setup to write the control"}, { ST_WRITE_MEM, "Write the control"}, { ST_WRITE_RATE, "Setup to write the sample rate to start mission"}, { ST_WRITE_MEM, "Write the sample rate"}, { ST_READ_STATUS, "Read the new mission status"}, { ST_FINISH, "Finished"}}; // external One Wire functions from nework layer extern SMALLINT owAccess(int); extern void owSerialNum(int,uchar *,SMALLINT); extern void owFamilySearchSetup(int,SMALLINT); extern SMALLINT owNext(int,SMALLINT,SMALLINT); extern SMALLINT owVerify(int,SMALLINT); extern SMALLINT owOverdriveAccess(int); // external One Wire functions from transaction layer extern SMALLINT owBlock(int,SMALLINT,uchar *,SMALLINT); // external One Wire functions from link layer extern SMALLINT owTouchReset(int); extern SMALLINT owWriteByte(int,SMALLINT); extern SMALLINT owSpeed(int,SMALLINT); extern void msDelay(int); // external functions defined in crcutil.c extern void setcrc16(int,ushort); extern ushort docrc16(int,ushort); // extern function prototypes extern int key_abort(void); // Local Function Prototypes int DownloadThermo(int,uchar *,ThermoStateType *,FILE *); int ReadThermoStatus(int,uchar *,ThermoStateType *,FILE *); int MissionThermo(int,uchar *,ThermoStateType *,FILE *); static int RunThermoScript(int,ThermoStateType *,ThermoScript script[],FILE *fp); void MissionStatusToString(MissionStatus *,int,char *); void SecondsToDate(timedate *, ulong); ulong DateToSeconds(timedate *); uchar BCDToBin(uchar); void InterpretStatus(MissionStatus *); void FormatMission(MissionStatus *); void InterpretHistogram(Histogram *); void HistogramToString(Histogram *, int, char *); void InterpretAlarms(TempAlarmEvents *, MissionStatus *); void AlarmsToString(TempAlarmEvents *, char *); void InterpretLog(Log *, MissionStatus *); void LogToString(Log *, int, char *); void DebugToString(MissionStatus *, TempAlarmEvents *, Histogram *, Log *, char *); float TempToFloat(uchar, int); float CToF(float); uchar ToBCD(short); static int ThermoStep(int,ThermoStateType *,ThermoScript *,int *,int *,int *,char *); static int ReadPages(int,int,int,int *,uchar *); static int WriteScratch(int,uchar *,int,int); static int CopyScratch(int,int,int); static int WriteMemory(int,uchar *, int, int); // global state information static int current_speed[MAX_PORTNUM]; //-------------------------------------------------------------------------- // The 'DownloadThermo' downloads the specified Thermochron in 'SerialNum' // and puts the data in the state variable 'ThermoState'. Progress output // is printed to the specified file 'fp'. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'SerialNum' - Device serial number to download // 'ThermoState' - pointer to a structure type that holds the raw and // translated Thermochron data. // 'fp' - file pointer to print status information to // // Returns: TRUE (1) : Thermochron download with raw data in ThermoState // FALSE (0): not downloaded. Abort due to repeated errors // or user keypress. // int DownloadThermo(int portnum, uchar *SerialNum, ThermoStateType *ThermoState, FILE *fp) { // set the serial num owSerialNum(portnum, SerialNum, FALSE); // run the script and download thermochron return RunThermoScript(portnum,ThermoState,Download,fp); } //-------------------------------------------------------------------------- // The 'ReadThermoStatus' reads the Thermochron status in 'SerialNum' // and puts the data in the state variable 'ThermoState'. Progress output // is printed to the specified file 'fp'. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'SerialNum' - Device serial number to download // 'ThermoState' - pointer to a structure type that holds the raw and // translated Thermochron data. // 'fp' - file pointer to print status information to // // Returns: TRUE (1) : Thermochron status read with raw data in ThermoState // FALSE (0): status not read. Abort due to repeated errors // or user keypress. // int ReadThermoStatus(int portnum, uchar *SerialNum, ThermoStateType *ThermoState, FILE *fp) { // set the serial num owSerialNum(portnum, SerialNum, FALSE); // run the script and read status of thermochron return RunThermoScript(portnum,ThermoState,GetStatus,fp); } //-------------------------------------------------------------------------- // The 'MissionThermo' starts a new Thermochron mission on 'SerialNum' // from the state information provided in 'ThermoState'. Progress output // is printed to the specified file 'fp'. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'SerialNum' - Device serial number to download // 'ThermoState' - pointer to a structure type that holds the raw and // translated Thermochron data. // 'fp' - file pointer to print status information to // // Returns: TRUE (1) : Thermochron missioned // FALSE (0): not missioned. Abort due to repeated errors // or user keypress. // int MissionThermo(int portnum, uchar *SerialNum, ThermoStateType *ThermoState,FILE *fp) { // set the serial num owSerialNum(portnum, SerialNum, FALSE); // run the script and mission thermochron return RunThermoScript(portnum,ThermoState,Mission,fp); } //-------------------------------------------------------------------------- // Run the specified script. Return TRUE if all steps completed else FALSE. // Status is printed to file 'fp'. // int RunThermoScript(int portnum, ThermoStateType *ThermoState, ThermoScript script[], FILE *fp) { char msg[256],LastDescription[256],LastMsg[256]; int StepCount,SubStep,ErrorCount,Status; int last_clear_step=0; // reset the step to the begining StepCount = 0; SubStep = 0; ErrorCount = 0; Status = STATUS_INPROGRESS; // loop to perform all of the steps to download the Thermochron do { // switch on the status of the last step done switch(Status) { // step complete so go to the next case STATUS_STEP_COMPLETE: StepCount++; SubStep = 0; ErrorCount = 0; Status = STATUS_INPROGRESS; LastDescription[0] = 0; LastMsg[0] = 0; break; // in progress so call again case STATUS_INPROGRESS: // record the step position of the last memory clear // this is in case we need to attempt a clear again if (script[StepCount].Step == ST_CLEAR_SETUP) last_clear_step = StepCount; // print step description if different if (strcmp(LastDescription, script[StepCount].StepDescription) != 0) { fprintf(fp,"%s --> ",script[StepCount].StepDescription); sprintf(LastDescription,"%s",script[StepCount].StepDescription); } // perform a step in the job ThermoStep(portnum,ThermoState,&script[StepCount],&SubStep, &Status, &ErrorCount, msg); // print results if different if (strcmp(LastMsg,msg) != 0) { fprintf(fp,"%s\n",msg); sprintf(LastMsg,"%s",msg); } else fprintf(fp,"."); break; // encountered a transient error case STATUS_ERROR_TRANSIENT: // check if transient error is a memory clear if (script[StepCount].Step == ST_CLEAR_VERIFY) { // put back to starting clear over again StepCount = last_clear_step; SubStep = 0; ErrorCount = 0; Status = STATUS_INPROGRESS; break; } // if 20 tansient errors in a row then abort if (ErrorCount > 20) Status = STATUS_ERROR_HALT; else Status = STATUS_INPROGRESS; break; // all steps complete case STATUS_COMPLETE: fprintf(fp,"End script normally\n"); return TRUE; break; // non-recoverable error case STATUS_ERROR_HALT: fprintf(fp,"Aborting script due to non-recoverable error\n"); return FALSE; break; } } while (!key_abort()); // key abort fprintf(fp,"Aborting script due to key press\n"); return FALSE; } //---------------------------------------------------------------------- // Use the script to perform a step and return. // int ThermoStep(int portnum, ThermoStateType *ThermoState, ThermoScript *StateScript, int *SubStep, int *Status, int *ErrorCount, char *msg) { short rslt; static int read_page_num, read_pages, write_addr, write_len; static uchar *read_buf, *write_buf; static uchar tbuf[5]; // do the current step switch (StateScript->Step) { // the operation is complete case ST_FINISH: sprintf(msg,"Operation complete"); *Status = STATUS_COMPLETE; break; // read the mission status page case ST_READ_STATUS: read_page_num = STATUS_PAGE; read_pages = 1; read_buf = ThermoState->MissStat.status_raw; sprintf(msg,"Ready to read status page %d", read_page_num); *Status = STATUS_STEP_COMPLETE; break; // set up to read the alarm registers case ST_READ_ALARM: read_page_num = 17; read_pages = 3; read_buf = ThermoState->AlarmData.alarm_raw; sprintf(msg,"Ready to read alarm pages %d to %d", read_page_num, read_page_num + read_pages - 1); *Status = STATUS_STEP_COMPLETE; break; // set up to read the histogram data case ST_READ_HIST: read_page_num = 64; read_pages = 4; read_buf = ThermoState->HistData.hist_raw; sprintf(msg,"Ready to read histogram pages %d to %d", read_page_num, read_page_num + read_pages - 1); *Status = STATUS_STEP_COMPLETE; break; // set up to read the log data case ST_READ_LOG: read_page_num = 128; read_pages = 64; read_buf = ThermoState->LogData.log_raw; sprintf(msg,"Ready to read log pages %d to %d", read_page_num, read_page_num + read_pages - 1); *Status = STATUS_STEP_COMPLETE; break; // read the specified pages case ST_READ_PAGES: // check for last page if (*SubStep == 0) // set the sub-step to the current page being read *SubStep = read_page_num; // read the status page rslt = ReadPages(portnum, read_page_num, read_pages, SubStep, read_buf); if (rslt == FALSE) { sprintf(msg,"Thermochron not on 1-Wire Net"); #ifdef __MC68K__ *Status = STATUS_ERROR_HALT; #else *Status = STATUS_INPROGRESS; #endif } else { sprintf(msg,"Pages read from Thermochron"); *Status = STATUS_STEP_COMPLETE; } break; // setup the clear memory case ST_CLEAR_SETUP: // create a small buff to write to start the clear memory tbuf[0] = 0x40; write_buf = &tbuf[0]; write_len = 1; write_addr = 0x20E; sprintf(msg,"Write to setup clear memory"); *Status = STATUS_STEP_COMPLETE; break; // clear the memory case ST_CLEAR_MEM: // set the clear memory command (not check return because verify) owAccess(portnum); owWriteByte(portnum,0x3C); msDelay(3); owTouchReset(portnum); sprintf(msg,"Clear memory command sent"); *Status = STATUS_STEP_COMPLETE; break; // clear the memory case ST_CLEAR_VERIFY: // look at the memory clear bit if ((ThermoState->MissStat.status_raw[0x14] & 0x40) == 0x40) { sprintf(msg,"Memory is clear"); *Status = STATUS_STEP_COMPLETE; break; } else { sprintf(msg,"Memory did NOT clear"); *Status = STATUS_ERROR_TRANSIENT; break; } break; // setup write time, clock alarm, control, trips case ST_WRITE_TIME: // create the write buffer FormatMission(&ThermoState->MissStat); write_buf = &ThermoState->MissStat.status_raw[0x00]; write_len = 13; write_addr = 0x200; sprintf(msg,"Write time, clock alarm, and trips setup"); *Status = STATUS_STEP_COMPLETE; break; // write the control, mission delay and clear flags case ST_WRITE_CONTROL: write_buf = &ThermoState->MissStat.status_raw[0x0E]; write_len = 7; write_addr = 0x20E; sprintf(msg,"Write control, mission delay, clear flags setup"); *Status = STATUS_STEP_COMPLETE; break; case ST_WRITE_RATE: write_buf = &ThermoState->MissStat.status_raw[0x0D]; write_len = 1; write_addr = 0x20D; sprintf(msg,"Write sample rate setup"); *Status = STATUS_STEP_COMPLETE; break; // write the specified memory location case ST_WRITE_MEM: if (WriteMemory(portnum, write_buf, write_len, write_addr)) { sprintf(msg,"Memory written to Thermochron"); *Status = STATUS_STEP_COMPLETE; } else { sprintf(msg,"Thermochron not on 1-Wire Net"); *Status = STATUS_INPROGRESS; } default: break; } return *Status; } //---------------------------------------------------------------------- // Read a specified number of pages in overdrive // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // int ReadPages(int portnum, int start_pg, int num_pgs, int *last_pg, uchar *finalbuf) { int skip_overaccess = 0, skip_access = 0; uchar pkt[60]; int len,i; uchar SerialNumber[8]; ushort lastcrc16; // read the rom number owSerialNum(portnum,SerialNumber,TRUE); #ifndef __MC68K__ // verify device is in overdrive if (current_speed[portnum] == MODE_OVERDRIVE) { if (owVerify(portnum,FALSE)) skip_overaccess = 1; } if (!skip_overaccess) { if (owOverdriveAccess(portnum)) current_speed[portnum] = MODE_OVERDRIVE; else current_speed[portnum] = MODE_NORMAL; } #endif // loop while there is pages to read do { // create a packet to read a page len = 0; setcrc16(portnum,0); // optional skip access on subsequent pages if (!skip_access) { // match pkt[len++] = 0x55; // rom number for (i = 0; i < 8; i++) pkt[len++] = SerialNumber[i]; // read memory with crc command pkt[len] = 0xA5; docrc16(portnum,pkt[len++]); // address pkt[len] = (uchar)((*last_pg << 5) & 0xFF); docrc16(portnum,pkt[len++]); pkt[len] = (uchar)(*last_pg >> 3); docrc16(portnum,pkt[len++]); } // set 32 reads for data and 2 for crc for (i = 0; i < 34; i++) pkt[len++] = 0xFF; // send the bytes if (owBlock(portnum,!skip_access,pkt,len)) { // calucate the CRC over the last 34 bytes for (i = 0; i < 34; i++) lastcrc16 = docrc16(portnum,pkt[len - 34 + i]); // check crc if (lastcrc16 == 0xB001) { // copy the data into the buffer for (i = 0; i < 32; i++) finalbuf[i + (*last_pg - start_pg) * 32] = pkt[len - 34 + i]; // change number of pages *last_pg = *last_pg + 1; // now skip access skip_access = TRUE; } else return FALSE; } else return FALSE; } while ((*last_pg - start_pg) < num_pgs); return TRUE; } //----------------------------------------------------------------------------} // Write a memory location. Data must all be on the same page // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // int WriteMemory(int portnum, uchar *Buf, int ln, int adr) { // write to scratch and then copy if (WriteScratch(portnum,Buf,ln,adr)) return CopyScratch(portnum,ln,adr); return FALSE; } //----------------------------------------------------------------------------} // Write the scratch pad // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // int WriteScratch(int portnum, uchar *Buf, int ln, int adr) { int i; uchar pbuf[80]; // check for alarm indicator if (owAccess(portnum)) { // construct a packet to send pbuf[0] = 0x0F; // write scratch command pbuf[1] = (adr & 0xFF); // address 1 pbuf[2] = ((adr >> 8) & 0xFF); // address 2 // the write bytes for (i = 0; i < ln; i++) pbuf[3 + i] = (uchar)(Buf[i]); // data // perform the block if (!owBlock(portnum,FALSE,pbuf,ln+3)) return FALSE; // Now read back the scratch if (owAccess(portnum)) { // construct a packet to send pbuf[0] = 0xAA; // read scratch command pbuf[1] = 0xFF; // address 1 pbuf[2] = 0xFF; // address 2 pbuf[3] = 0xFF; // offset // the write bytes for (i = 0; i < ln; i++) pbuf[4 + i] = 0xFF; // data // perform the block if (!owBlock(portnum,FALSE,pbuf,ln+4)) return FALSE; // read address 1 if (pbuf[1] != (adr & 0xFF)) return FALSE; // read address 2 if (pbuf[2] != ((adr >> 8) & 0xFF)) return FALSE; // read the offset if (pbuf[3] != ((adr + ln - 1) & 0x1F)) return FALSE; // read and compare the contents for (i = 0; i < ln; i++) { if (pbuf[4 + i] != Buf[i]) return FALSE; } // success return TRUE; } } return FALSE; } //----------------------------------------------------------------------------} // Copy the scratch pad // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // int CopyScratch(int portnum, int ln, int adr) { int i; uchar pbuf[50]; // check for alarm indicator if (owAccess(portnum)) { // construct a packet to send pbuf[0] = 0x55; // copy scratch command pbuf[1] = (adr & 0xFF); // address 1 pbuf[2] = ((adr >> 8) & 0xFF); // address 2 pbuf[3] = (adr + ln - 1) & 0x1F; // offset for (i = 0; i <= 9; i++) pbuf[4 + i] = 0xFF; // result of copy // perform the block if (owBlock(portnum,FALSE,pbuf,14)) { if ((pbuf[13] == 0x55) || (pbuf[13] == 0xAA)) return TRUE; } } return FALSE; } //---------------------------------------------------------------------- // Interpret the Status by looking at the 'raw' portion of the // mission status structure. // void InterpretStatus(MissionStatus *mstatus) { timedate td,tdtmp; int offset; ulong tmtmp; #ifndef __MC68K__ time_t tlong; struct tm *tstruct; #endif // mission in progress flag mstatus->mission_in_progress = (0x20 & mstatus->status_raw[0x14]) >> 5; // sample rate mstatus->sample_rate = mstatus->status_raw[0x0D]; // rollover enabled mstatus->rollover_enable = (0x08 & mstatus->status_raw[0x0E]) >> 3; // startdelay mstatus->start_delay = (mstatus->status_raw[0x13] << 8) | mstatus->status_raw[0x12]; // number of samples in this mission #ifdef __MC68K__ mstatus->mission_samples = (((ulong) mstatus->status_raw[0x1C]) * 65536) + (((ulong) mstatus->status_raw[0x1B]) * 256) + ((ulong) mstatus->status_raw[0x1A]); #else mstatus->mission_samples = (mstatus->status_raw[0x1C] << 16) | (mstatus->status_raw[0x1B] << 8) | mstatus->status_raw[0x1A]; #endif // total number of samples #ifdef __MC68K__ mstatus->samples_total = (((ulong) mstatus->status_raw[0x1F]) * 65536) + (((ulong) mstatus->status_raw[0x1E]) * 256) + ((ulong) mstatus->status_raw[0x1D]); #else mstatus->samples_total = (mstatus->status_raw[0x1F] << 16) | (mstatus->status_raw[0x1E] << 8) | mstatus->status_raw[0x1D]; #endif // temperature thresholds mstatus->high_threshold = mstatus->status_raw[0x0C]; mstatus->low_threshold = mstatus->status_raw[0x0B]; // rollover occurred if ((mstatus->mission_samples > 2048) && mstatus->rollover_enable) mstatus->rollover_occurred = 1; else mstatus->rollover_occurred = 0; // current real-time clock value offset = 0x00; td.second = BCDToBin((uchar)(mstatus->status_raw[offset] & 0x7F)); td.minute = BCDToBin((uchar)(mstatus->status_raw[offset + 1] & 0x7F)); // check for 12 hour mode if (mstatus->status_raw[offset + 2] & 0x40) { td.hour = BCDToBin((uchar)(mstatus->status_raw[offset + 2] & 0x1F)); // check for PM if (mstatus->status_raw[offset + 2] & 0x20) td.hour += 12; } else td.hour = BCDToBin((uchar)(mstatus->status_raw[offset + 2] & 0x3F)); td.day = BCDToBin((uchar)(mstatus->status_raw[offset + 4] & 0x3F)); td.month = BCDToBin((uchar)(mstatus->status_raw[offset + 5] & 0x1F)); td.year = BCDToBin(mstatus->status_raw[offset + 6]) + 1900; // check for century bit if (mstatus->status_raw[offset + 5] & 0x80) td.year = BCDToBin(mstatus->status_raw[offset + 6]) + 2000; // (2.00) // convert to seconds since 1970 mstatus->current_time = DateToSeconds(&td); // date/time when mission started offset = 0x15; td.second = (uchar)0; td.minute = BCDToBin((uchar)(mstatus->status_raw[offset] & 0x7F)); // check for 12 hour mode if (mstatus->status_raw[offset + 1] & 0x40) { td.hour = BCDToBin((uchar)(mstatus->status_raw[offset + 1] & 0x1F)); // check for PM if (mstatus->status_raw[offset + 1] & 0x20) td.hour += 12; } else td.hour = BCDToBin((uchar)(mstatus->status_raw[offset + 1] & 0x3F)); td.day = BCDToBin((uchar)(mstatus->status_raw[offset + 2] & 0x3F)); td.month = BCDToBin((uchar)(mstatus->status_raw[offset + 3] & 0x1F)); td.year = BCDToBin((uchar)(mstatus->status_raw[offset + 4])); // (2.00) // (2.00) logic to decide on century of mission stamp // check if century bit set in mission stamp if (mstatus->status_raw[offset + 3] & 0x80) td.year += 2000; // check in mission in progress else if (mstatus->mission_in_progress) { // calculate the mission start year back from real time clock tmtmp = mstatus->current_time - (mstatus->sample_rate * mstatus->mission_samples * 60); SecondsToDate(&tdtmp,tmtmp); td.year = tdtmp.year; } else { // mission stopped so get century by year window if (td.year <= 70) td.year += 2000; else td.year += 1900; } // convert to seconds since 1970 if ((td.month == 0) || (td.day == 0)) mstatus->mission_start_time = 0; else mstatus->mission_start_time = DateToSeconds(&td); // download stations time of reading #ifdef __MC68K__ mstatus->download_time = TimGetSeconds(); #else time(&tlong); tstruct = localtime(&tlong); td.day = tstruct->tm_mday; td.month = tstruct->tm_mon + 1; // (1.01) td.year = tstruct->tm_year + 1900; td.hour = tstruct->tm_hour; td.minute = tstruct->tm_min; td.second = tstruct->tm_sec; mstatus->download_time = DateToSeconds(&td); #endif // skip alarm modes and status for now } //-------------------------------------------------------------------------- // Take the Mission Status structure and create new raw data to start // a new mission. // void FormatMission(MissionStatus *mstatus) { int i; time_t tlong; #ifndef __MC68K__ struct tm *tstruct; #else DateTimePtr tstruct = NULL; #endif // clear the buffer for (i = 0; i < 32; i++) mstatus->status_raw[i] = 0; // Real Time Clock #ifdef __MC68K__ tlong = TimGetSeconds(); #else time(&tlong); #endif tlong++; // add 1 second #ifdef __MC68K__ TimSecondsToDateTime(tlong, tstruct); #else tstruct = localtime(&tlong); #endif // convert to BCD #ifdef __MC68K__ mstatus->status_raw[0x00] = ToBCD((short)tstruct->second); mstatus->status_raw[0x01] = ToBCD((short)tstruct->minute); mstatus->status_raw[0x02] = ToBCD((short)tstruct->hour); mstatus->status_raw[0x03] = ToBCD((short)(tstruct->weekDay + 1)); mstatus->status_raw[0x04] = ToBCD((short)tstruct->day); mstatus->status_raw[0x05] = ToBCD((short)(tstruct->month + 1)); if (tstruct->year >= 100) mstatus->status_raw[0x05] |= 0x80; mstatus->status_raw[0x06] = ToBCD((short)(tstruct->year % 100)); #else mstatus->status_raw[0x00] = ToBCD((short)tstruct->tm_sec); mstatus->status_raw[0x01] = ToBCD((short)tstruct->tm_min); mstatus->status_raw[0x02] = ToBCD((short)tstruct->tm_hour); mstatus->status_raw[0x03] = ToBCD((short)(tstruct->tm_wday + 1)); mstatus->status_raw[0x04] = ToBCD((short)tstruct->tm_mday); mstatus->status_raw[0x05] = ToBCD((short)(tstruct->tm_mon + 1)); if (tstruct->tm_year >= 100) mstatus->status_raw[0x05] |= 0x80; mstatus->status_raw[0x06] = ToBCD((short)(tstruct->tm_year % 100)); #endif // Real Time clock Alarm (leave 0's) // Low temp alarm mstatus->status_raw[0x0B] = mstatus->low_threshold; // High temp alarm mstatus->status_raw[0x0C] = mstatus->high_threshold; // sample rate mstatus->status_raw[0x0D] = mstatus->sample_rate; // control mstatus->status_raw[0x0E] = 0x40; if (mstatus->rollover_enable) mstatus->status_raw[0x0E] |= 0x08; // mission start delay mstatus->status_raw[0x12] = mstatus->start_delay & 0xFF; mstatus->status_raw[0x13] = (mstatus->start_delay >> 8) & 0xFF; } //-------------------------------------------------------------------------- // Convert an integer to a 1 Byte BCD number (99 max) // uchar ToBCD(short num) { uchar rtbyte; rtbyte = (num - ((num / 10) * 10)) & 0x0F; rtbyte = rtbyte | ((num / 10) << 4); return rtbyte; } //-------------------------------------------------------------------------- // Take the Mission Status structure and convert to string format // void MissionStatusToString(MissionStatus *mstatus, int ConvertToF, char *str) { int cnt=0,i; timedate td; #ifndef __MC68K__ time_t tlong; struct tm *tstruct; #else DateTimePtr tstruct = NULL; #endif // title #ifdef __MC68K__ cnt += sprintf(&str[cnt],"Stat For DS1921:"); #else cnt += sprintf(&str[cnt],"Mission State\n-------------\n"); cnt += sprintf(&str[cnt],"Serial Number of DS1921: "); #endif // serial number for (i = 7; i >= 0; i--) cnt += sprintf(&str[cnt],"%02X",mstatus->serial_num[i]); // mission state if (mstatus->mission_in_progress) cnt += sprintf(&str[cnt],"\nMission is in progress\n"); else cnt += sprintf(&str[cnt],"\nMission is ended\n"); // sample rate cnt += sprintf(&str[cnt],"Sample rate: %d minute(s)\n",mstatus->sample_rate); // rollover cnt += sprintf(&str[cnt],"Roll-Over Enabled: "); if (mstatus->rollover_enable) cnt += sprintf(&str[cnt],"yes\n"); else cnt += sprintf(&str[cnt],"no\n"); cnt += sprintf(&str[cnt],"Roll-Over Occurred: "); if (mstatus->rollover_occurred) cnt += sprintf(&str[cnt],"yes\n"); else cnt += sprintf(&str[cnt],"no\n"); // mission start time if (mstatus->start_delay == 0) { SecondsToDate(&td,mstatus->mission_start_time); if (mstatus->mission_start_time == 0) cnt += sprintf(&str[cnt],"Mission Start time: not started yet\n"); else cnt += sprintf(&str[cnt],"Mission Start: %02d/%02d/%04d %02d:%02d:%02d\n", td.month,td.day,td.year,td.hour,td.minute,td.second); } else cnt += sprintf(&str[cnt],"Mission Start time: na\n"); // mission start delay cnt += sprintf(&str[cnt],"Mission Start delay: %d minute(s)\n",mstatus->start_delay); // mission samples cnt += sprintf(&str[cnt],"Mission Samples: %ld\n",mstatus->mission_samples); // device total samples cnt += sprintf(&str[cnt],"Device total samples: %ld\n",mstatus->samples_total); // temperature display mode cnt += sprintf(&str[cnt],"Temp displayed in: "); if (ConvertToF) cnt += sprintf(&str[cnt],"(Fahrenheit)\n"); else cnt += sprintf(&str[cnt],"(Celsius)\n"); // thresholds cnt += sprintf(&str[cnt],"High Threshold: %6.1f\n", TempToFloat(mstatus->high_threshold,ConvertToF)); cnt += sprintf(&str[cnt],"Low Threshold: %6.1f\n", TempToFloat(mstatus->low_threshold,ConvertToF)); // time from D1921 SecondsToDate(&td,mstatus->current_time); cnt += sprintf(&str[cnt],"Current Real-Time Clock from DS1921: %02d/%02d/%04d %02d:%02d:%02d\n", td.month,td.day,td.year,td.hour,td.minute,td.second); #ifndef __MC68K__ // current PC time time(&tlong); tstruct = localtime(&tlong); cnt += sprintf(&str[cnt],"Current PC Time: %02d/%02d/%04d %02d:%02d:%02d\n", tstruct->tm_mon + 1,tstruct->tm_mday,tstruct->tm_year + 1900, tstruct->tm_hour,tstruct->tm_min,tstruct->tm_sec); #endif // zero terminate string str[cnt] = 0; } //---------------------------------------------------------------------- // Interpret the Histogram by looking at the 'raw' portion of the // Histogram structure. Store the temperature range values in Celsius. // void InterpretHistogram(Histogram *hist) { int i; // loop through each bin value for (i = 0; i < 126; i += 2) // (2.00) { // get the bin value hist->bin_count[i / 2] = hist->hist_raw[i] | (hist->hist_raw[i + 1] << 8); // start value for this bin hist->start_range[i / 2] = TempToFloat((uchar)((i / 2) << 2),FALSE); // end value for this bin hist->end_range[i / 2] = TempToFloat((uchar)(((i / 2) << 2) | 0x03),FALSE); } } //-------------------------------------------------------------------------- // Take the Histogram structure and convert to string format // void HistogramToString(Histogram *hist, int ConvertToF, char *str) { int cnt=0,i; // title cnt += sprintf(&str[cnt],"Temperature Histogram\n---------------------\n" "Format: [Temp Range, Count] "); if (ConvertToF) cnt += sprintf(&str[cnt],"(Fahrenheit)\n"); else cnt += sprintf(&str[cnt],"(Celsius)\n"); // loop through bins for (i = 0; i < 63; i++) // (2.00) { cnt += sprintf(&str[cnt],"%6.1f to %6.1f, %d\n", (ConvertToF) ? CToF(hist->start_range[i]): hist->start_range[i], (ConvertToF) ? CToF(hist->end_range[i]): hist->end_range[i], hist->bin_count[i]); } // zero terminate string str[cnt] = 0; } //---------------------------------------------------------------------- // Interpret the Temperature Alarm Event data by looking at the 'raw' // portion of the TempAlarmEvents structure. Mission Status is needed // to interpret the events. // void InterpretAlarms(TempAlarmEvents *alarm, MissionStatus *mstatus) { int i; ulong event_mission_count; uchar duration; // low events alarm->num_low = 0; for (i = 0; i < 48; i += 4) { // get the mission start count of this event event_mission_count = (alarm->alarm_raw[i + 2] << 16) | (alarm->alarm_raw[i + 1] << 8) | alarm->alarm_raw[i]; // check if done with low events if (!event_mission_count) break; // get the duration duration = alarm->alarm_raw[i + 3]; // calculate the start time alarm->low_start_time[alarm->num_low] = mstatus->mission_start_time + (event_mission_count - 1) * (mstatus->sample_rate * 60); // calculate the end time alarm->low_end_time[alarm->num_low] = alarm->low_start_time[alarm->num_low] + (duration - 1) * (mstatus->sample_rate * 60); // increment number of low events alarm->num_low++; } // high events alarm->num_high = 0; for (i = 48; i < 96; i += 4) { // get the mission start count of this event event_mission_count = (alarm->alarm_raw[i + 2] << 16) | (alarm->alarm_raw[i + 1] << 8) | alarm->alarm_raw[i]; // check if done with low events if (!event_mission_count) break; // get the duration duration = alarm->alarm_raw[i + 3]; // calculate the start time alarm->high_start_time[alarm->num_high] = mstatus->mission_start_time + (event_mission_count - 1) * (mstatus->sample_rate * 60); // calculate the end time alarm->high_end_time[alarm->num_high] = alarm->high_start_time[alarm->num_high] + (duration - 1) * (mstatus->sample_rate * 60); // increment number of low events alarm->num_high++; } } //-------------------------------------------------------------------------- // Take the Temperature Alarms Events structure and convert to string // format // void AlarmsToString(TempAlarmEvents *alarm, char *str) { int i, cnt=0; timedate td; // title cnt += sprintf(&str[cnt],"Temperature Alarms\n------------------\n" "Format: [(HIGH/LOW), Time/Date Range]\n"); // loop through each low alarm for (i = 0; i < alarm->num_low; i++) { cnt += sprintf(&str[cnt],"LOW , "); // start time SecondsToDate(&td,alarm->low_start_time[i]); cnt += sprintf(&str[cnt]," %02d/%02d/%04d %02d:%02d to ", td.month,td.day,td.year,td.hour,td.minute); // end time SecondsToDate(&td,alarm->low_end_time[i]); cnt += sprintf(&str[cnt]," %02d/%02d/%04d %02d:%02d\n", td.month,td.day,td.year,td.hour,td.minute); } // loop through each high alarm for (i = 0; i < alarm->num_high; i++) { cnt += sprintf(&str[cnt],"HIGH , "); // start time SecondsToDate(&td,alarm->high_start_time[i]); cnt += sprintf(&str[cnt]," %02d/%02d/%04d %02d:%02d to ", td.month,td.day,td.year,td.hour,td.minute); // end time SecondsToDate(&td,alarm->high_end_time[i]); cnt += sprintf(&str[cnt]," %02d/%02d/%04d %02d:%02d\n", td.month,td.day,td.year,td.hour,td.minute); } // zero terminate string str[cnt] = 0; } //---------------------------------------------------------------------- // Interpret the Log data by looking at the 'raw' // portion of the Log structure. Mission Status is needed // to interpret when the logs occurred. // void InterpretLog(Log *log, MissionStatus *mstatus) { ulong loops=0,overlap=0,lastlog=2048,i; int logcnt=0; // check if wrap occurred if (mstatus->rollover_occurred) { // calculate the number loops loops = (mstatus->mission_samples / 2048) - 1; // calculate the number of overlap overlap = mstatus->mission_samples % 2048; log->num_log = 2048; } else { log->start_time = mstatus->mission_start_time; if (mstatus->mission_samples > 2048) // (1.02) lastlog = 2048; else lastlog = mstatus->mission_samples; log->num_log = (int)lastlog; } // set the interval log->interval = mstatus->sample_rate * 60; // caluclate the start time of the first log value log->start_time = mstatus->mission_start_time + loops * 2048 * log->interval + overlap * log->interval; // loop to fill in the remainder first for (i = overlap; i < lastlog; i++) log->temp[logcnt++] = TempToFloat(log->log_raw[i],FALSE); // loop to get the overlap for (i = 0; i < overlap; i++) log->temp[logcnt++] = TempToFloat(log->log_raw[i],FALSE); } //-------------------------------------------------------------------------- // Take the Log structure and convert to string // format // void LogToString(Log *log, int ConvertToF, char *str) { int i,cnt=0; ulong logtime; timedate td; // title cnt += sprintf(&str[cnt],"Log Data\n--------\n" "Format: [Time/Date , Temperature] "); if (ConvertToF) cnt += sprintf(&str[cnt],"(Fahrenheit)\n"); else cnt += sprintf(&str[cnt],"(Celsius)\n"); // loop through the logs logtime = log->start_time; for (i = 0; i < log->num_log; i++) { // time SecondsToDate(&td,logtime); cnt += sprintf(&str[cnt],"%02d/%02d/%04d %02d:%02d ,", td.month,td.day,td.year,td.hour,td.minute); // temp cnt += sprintf(&str[cnt],"%6.1f\n", (ConvertToF) ? CToF(log->temp[i]): log->temp[i]); // increment the time logtime += log->interval; } // zero terminate string str[cnt] = 0; } //-------------------------------------------------------------------------- // Convert the raw debug data to a string // void DebugToString(MissionStatus *mstatus, TempAlarmEvents *alarm, Histogram *hist, Log *log, char *str) { int i,cnt=0; // title cnt += sprintf(&str[cnt],"Debug Dump\n----------\nRegister Page:\n"); // reg for (i = 0; i < 32; i++) { cnt += sprintf(&str[cnt],"%02X ",mstatus->status_raw[i]); if (i && (((i + 1) % 16) == 0)) cnt += sprintf(&str[cnt],"\n"); } // alarms cnt += sprintf(&str[cnt],"Alarms:\n"); for (i = 0; i < 96; i++) { cnt += sprintf(&str[cnt],"%02X ",alarm->alarm_raw[i]); if (i && (((i + 1) % 16) == 0)) cnt += sprintf(&str[cnt],"\n"); } // histogram cnt += sprintf(&str[cnt],"Histogram:\n"); for (i = 0; i < 128; i++) { cnt += sprintf(&str[cnt],"%02X ",hist->hist_raw[i]); if (i && (((i + 1) % 16) == 0)) cnt += sprintf(&str[cnt],"\n"); } // log cnt += sprintf(&str[cnt],"Log:\n"); for (i = 0; i < ((log->num_log > 2048) ? 2048 : log->num_log); i++) { cnt += sprintf(&str[cnt],"%02X ",log->log_raw[i]); if (i && (((i + 1) % 16) == 0)) cnt += sprintf(&str[cnt],"\n"); } // zero terminate string str[cnt] = 0; } //-------------------------------------------------------------------------- // Take one byte BCD value and return binary value // uchar BCDToBin(uchar bcd) { return (((bcd & 0xF0) >> 4) * 10) + (bcd & 0x0F); } //-------------------------------------------------------------------------- // Take a 4 byte long string and convert it into a timedata structure. // static int dm[] = { 0,0,31,59,90,120,151,181,212,243,273,304,334,365 }; void SecondsToDate(timedate *td, ulong x) { short tmp,i,j; ulong y; // check to make sure date is not over 2070 (sanity check) if (x > 0xBBF81E00L) x = 0; y = x/60; td->second = (ushort)(x-60*y); x = y/60; td->minute = (ushort)(y-60*x); y = x/24; td->hour = (ushort)(x-24*y); x = 4*(y+731); td->year = (ushort)(x/1461); i = (int)((x-1461*(ulong)(td->year))/4); td->month = 13; do { td->month -= 1; tmp = (td->month > 2) && ((td->year & 3)==0) ? 1 : 0; j = dm[td->month]+tmp; } while (i < j); td->day = i-j+1; // slight adjustment to algorithm if (td->day == 0) td->day = 1; td->year = (td->year < 32) ? td->year + 68 + 1900: td->year - 32 + 2000; } //-------------------------------------------------------------------------- // DateToSeconds takes a time/date structure and converts it into the // number of seconds since 1970 // ulong DateToSeconds(timedate *td) { ulong Sv,Bv,Xv; // convert the date/time values into the 5 byte format used in the touch if (td->year >= 2000) Sv = td->year + 32 - 2000; else Sv = td->year - 68 - 1900; if ((td->month > 2) && ( (Sv & 3) == 0)) Bv = 1; else Bv = 0; Xv = 365 * (Sv-2) + (Sv-1)/4 + dm[td->month] + td->day + Bv - 1; Xv = 86400 * Xv + (ulong)(td->second) + 60*((ulong)(td->minute) + 60*(ulong)(td->hour)); return Xv; } //-------------------------------------------------------------------------- // Convert from DS1921 termature format to a float // // float TempToFloat(uchar tmp, int ConvertToF) { float tfloat; tfloat = (float)((tmp / 2.0) - 40.0); if (ConvertToF) return (float)(tfloat * 9.0 / 5.0 + 32.0); else return tfloat; } //-------------------------------------------------------------------------- // Convert from Celsius to Fahrenheit // float CToF(float CVal) { return (float)(CVal * 9.0 / 5.0 + 32.0); } digitemp-3.6.0+dfsg1/userial/crcutil.c0000644000175000017500000001153210632073746016315 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //-------------------------------------------------------------------------- // // crcutil.c - Keeps track of the CRC for 16 and 8 bit operations // version 2.00 // Include files #include "ownet.h" // Local subroutines void setcrc16(int,ushort); ushort docrc16(int,ushort); void setcrc8(int,uchar); uchar docrc8(int,uchar); // Local global variables ushort utilcrc16[MAX_PORTNUM]; uchar utilcrc8[MAX_PORTNUM]; static short oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }; static 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}; //-------------------------------------------------------------------------- // Reset crc16 to the value passed in // // 'reset' - data to set crc16 to. // void setcrc16(int portnum, ushort reset) { utilcrc16[portnum] = reset; return; } //-------------------------------------------------------------------------- // Reset crc8 to the value passed in // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'reset' - data to set crc8 to // void setcrc8(int portnum, uchar reset) { utilcrc8[portnum] = reset; return; } //-------------------------------------------------------------------------- // Calculate a new CRC16 from the input data short. Return the current // CRC16 and also update the global variable CRC16. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'data' - data to perform a CRC16 on // // Returns: the current CRC16 // ushort docrc16(int portnum, ushort cdata) { cdata = (cdata ^ (utilcrc16[portnum] & 0xff)) & 0xff; utilcrc16[portnum] >>= 8; if (oddparity[cdata & 0xf] ^ oddparity[cdata >> 4]) utilcrc16[portnum] ^= 0xc001; cdata <<= 6; utilcrc16[portnum] ^= cdata; cdata <<= 1; utilcrc16[portnum] ^= cdata; return utilcrc16[portnum]; } //-------------------------------------------------------------------------- // Update the Dallas Semiconductor One Wire CRC (utilcrc8) from the global // variable utilcrc8 and the argument. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'x' - data byte to calculate the 8 bit crc from // // Returns: the updated utilcrc8. // uchar docrc8(int portnum, uchar x) { utilcrc8[portnum] = dscrc_table[utilcrc8[portnum] ^ x]; return utilcrc8[portnum]; } digitemp-3.6.0+dfsg1/userial/cnt1d.c0000644000175000017500000001050610632073746015661 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // cnt1D.c - Module to read the DS2423 - counter. // // Version: 2.00 // // #include "ownet.h" // external One Wire functions from nework layer extern SMALLINT owAccess(int); extern void owSerialNum(int,uchar *,SMALLINT); extern SMALLINT owVerify(int,SMALLINT); // external One Wire functions from transaction layer extern SMALLINT owBlock(int,SMALLINT,uchar *,SMALLINT); // external functions defined in crcutil.c extern void setcrc16(int,ushort); extern ushort docrc16(int,ushort); // exportable functions defined in cnt1d.c SMALLINT ReadCounter(int,int,ulong *); //---------------------------------------------------------------------- // Read the counter on a specified page of a DS2423. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'SerialNum' - Serial Number of DS2423 that contains the counter // to be read // 'CounterPage' - page number that the counter is associated with // 'Count' - pointer to variable where that count will be returned // // Returns: TRUE(1) counter has been read and verified // FALSE(0) could not read the counter, perhaps device is not // in contact // SMALLINT ReadCounter(int portnum, int CounterPage, unsigned long *Count) { uchar rt=FALSE; uchar send_block[30]; uchar send_cnt=0, i; int address; ushort lastcrc16; setcrc16(portnum,0); // set the device serial number to the counter device /* 2/12/2003 [bcl] DigiTemp does this before calling the routine */ /* owSerialNum(portnum,SerialNum,FALSE); */ // access the device if (owAccess(portnum)) { // create a block to send that reads the counter // read memory and counter command send_block[send_cnt++] = 0xA5; docrc16(portnum,0xA5); // address of last data byte before counter address = (CounterPage << 5) + 31; // (1.02) send_block[send_cnt++] = (uchar)(address & 0xFF); docrc16(portnum,(ushort)(address & 0xFF)); send_block[send_cnt++] = (uchar)(address >> 8); docrc16(portnum,(ushort)(address >> 8)); // now add the read bytes for data byte,counter,zero bits, crc16 for (i = 0; i < 11; i++) send_block[send_cnt++] = 0xFF; // now send the block if (owBlock(portnum,FALSE,send_block,send_cnt)) { // perform the CRC16 on the last 11 bytes of packet for (i = send_cnt - 11; i < send_cnt; i++) lastcrc16 = docrc16(portnum,send_block[i]); // verify CRC16 is correct if (lastcrc16 == 0xB001) { // success rt = TRUE; // extract the counter value *Count = 0; for (i = send_cnt - 7; i >= send_cnt - 10; i--) { *Count <<= 8; *Count |= send_block[i]; } } } } // return the result flag rt return rt; } digitemp-3.6.0+dfsg1/userial/ownet.h0000644000175000017500000003063110632260144016000 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // ownet.h - Include file for 1-Wire Net library // // Version: 2.10 // // History: 1.02 -> 1.03 Make sure uchar is not defined twice. // 1.03 -> 2.00 Changed 'MLan' to 'ow'. // 2.00 -> 2.01 Added error handling. Added circular-include check. // 2.01 -> 2.10 Added raw memory error handling and SMALLINT // 2.10 -> 3.00 Added memory bank functionality // Added file I/O operations // #ifndef OWNET_H #define OWNET_H //--------------------------------------------------------------// // Target Specific Information //--------------------------------------------------------------// //--------------------------------------------------------------// // Handhelds (PalmOS, WinCE) //--------------------------------------------------------------// #ifdef __MC68K__ //MC68K is the type of processor in the PILOT //Metrowerk's CodeWarrior defines this symbol #include #ifndef strcmp #include #define strcmp StrCompare #endif #endif #ifdef _WIN32_WCE //All of our projects had this flag defined by default (_WIN32_WCE), //but I'm not 100% positive that this is _the_ definitive //flag to use to identify a WinCE system. #include "WinCElnk.h" #endif #ifdef _WIN32_WCE #ifndef FILE #define FILE int extern int sprintf(char *buffer, char *format,...); extern void fprintf(FILE *fp, char *format,...); extern void printf(char *format,...); #endif #endif #ifdef __MC68K__ #include #endif #if !defined(_WIN32_WCE) && !defined(__MC68K__) #include #endif #ifdef __C51__ #define FILE int extern void fprintf (FILE*fileNo,char*s,...); #define exit(c) return #define key_abort() (FALSE) typedef unsigned int ushort; typedef unsigned long ulong; #define SMALLINT uchar #endif #ifdef SOLARIS #include #include #endif //--------------------------------------------------------------// // Common Includes to ownet applications //--------------------------------------------------------------// #include //--------------------------------------------------------------// // Typedefs //--------------------------------------------------------------// #ifndef SMALLINT // // purpose of smallint is for compile-time changing of formal // parameters and return values of functions. For each target // machine, an integer is alleged to represent the most "simple" // number representable by that architecture. This should, in // most cases, produce optimal code for that particular arch. // BUT... The majority of compilers designed for embedded // processors actually keep an int at 16 bits, although the // architecture might only be comfortable with 8 bits. // The default size of smallint will be the same as that of // an integer, but this allows for easy overriding of that size. // // NOTE: // In all cases where a smallint is used, it is assumed that // decreasing the size of this integer to something as low as // a single byte _will_not_ change the functionality of the // application. e.g. a loop counter that will iterate through // several kilobytes of data should not be SMALLINT. The most // common place you'll see smallint is for boolean return types. // #define SMALLINT int #endif #ifndef OW_UCHAR #define OW_UCHAR typedef unsigned char uchar; #ifdef __CYGWIN__ //&& GCC typedef unsigned long ulong; //ushort already defined in CygWin, in sys/types.h #include #else #if defined(FREEBSD) || defined(_WIN32) || defined(WIN32) || defined(__MC68K__) || defined(_WIN32_WCE) typedef unsigned short ushort; typedef unsigned long ulong; #endif #if defined(DARWIN) typedef unsigned short ushort; typedef unsigned long ulong; #endif #endif #ifdef SDCC //intent of ushort is 2 bytes unsigned. //for ds390 in sdcc, an int, not a short, //is 2 bytes. typedef unsigned int ushort; #endif #endif // general defines #define WRITE_FUNCTION 1 #define READ_FUNCTION 0 // error codes // todo: investigate these and replace with new Error Handling library #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 #ifndef MAX_PORTNUM #define MAX_PORTNUM 16 #endif // mode bit flags #define MODE_NORMAL 0x00 #define MODE_OVERDRIVE 0x01 #define MODE_STRONG5 0x02 #define MODE_PROGRAM 0x04 #define MODE_BREAK 0x08 // Output flags #define LV_ALWAYS 2 #define LV_OPTIONAL 1 #define LV_VERBOSE 0 //--------------------------------------------------------------// // Error handling //--------------------------------------------------------------// extern int owGetErrorNum(void); extern int owHasErrors(void); //Clears the stack. #define OWERROR_CLEAR() while(owHasErrors()) owGetErrorNum(); #ifdef DEBUG //Raises an exception with extra debug info #define OWERROR(err) owRaiseError(err,__LINE__,__FILE__) extern void owRaiseError(int,int,char*); #define OWASSERT(s,err,ret) if(!(s)){owRaiseError((err),__LINE__,__FILE__);return (ret);} #else //Raises an exception with just the error code #define OWERROR(err) owRaiseError(err) extern void owRaiseError(int); #define OWASSERT(s,err,ret) if(!(s)){owRaiseError((err));return (ret);} #endif #ifdef SMALL_MEMORY_TARGET #define OWERROR_DUMP(fileno) /*no-op*/; #else //Prints the stack out to the given file. #define OWERROR_DUMP(fileno) while(owHasErrors()) owPrintErrorMsg(fileno); extern void owPrintErrorMsg(FILE *); extern void owPrintErrorMsgStd(); extern char *owGetErrorMsg(int); #endif #define OWERROR_NO_ERROR_SET 0 #define OWERROR_NO_DEVICES_ON_NET 1 #define OWERROR_RESET_FAILED 2 #define OWERROR_SEARCH_ERROR 3 #define OWERROR_ACCESS_FAILED 4 #define OWERROR_DS2480_NOT_DETECTED 5 #define OWERROR_DS2480_WRONG_BAUD 6 #define OWERROR_DS2480_BAD_RESPONSE 7 #define OWERROR_OPENCOM_FAILED 8 #define OWERROR_WRITECOM_FAILED 9 #define OWERROR_READCOM_FAILED 10 #define OWERROR_BLOCK_TOO_BIG 11 #define OWERROR_BLOCK_FAILED 12 #define OWERROR_PROGRAM_PULSE_FAILED 13 #define OWERROR_PROGRAM_BYTE_FAILED 14 #define OWERROR_WRITE_BYTE_FAILED 15 #define OWERROR_READ_BYTE_FAILED 16 #define OWERROR_WRITE_VERIFY_FAILED 17 #define OWERROR_READ_VERIFY_FAILED 18 #define OWERROR_WRITE_SCRATCHPAD_FAILED 19 #define OWERROR_COPY_SCRATCHPAD_FAILED 20 #define OWERROR_INCORRECT_CRC_LENGTH 21 #define OWERROR_CRC_FAILED 22 #define OWERROR_GET_SYSTEM_RESOURCE_FAILED 23 #define OWERROR_SYSTEM_RESOURCE_INIT_FAILED 24 #define OWERROR_DATA_TOO_LONG 25 #define OWERROR_READ_OUT_OF_RANGE 26 #define OWERROR_WRITE_OUT_OF_RANGE 27 #define OWERROR_DEVICE_SELECT_FAIL 28 #define OWERROR_READ_SCRATCHPAD_VERIFY 29 #define OWERROR_COPY_SCRATCHPAD_NOT_FOUND 30 #define OWERROR_ERASE_SCRATCHPAD_NOT_FOUND 31 #define OWERROR_ADDRESS_READ_BACK_FAILED 32 #define OWERROR_EXTRA_INFO_NOT_SUPPORTED 33 #define OWERROR_PG_PACKET_WITHOUT_EXTRA 34 #define OWERROR_PACKET_LENGTH_EXCEEDS_PAGE 35 #define OWERROR_INVALID_PACKET_LENGTH 36 #define OWERROR_NO_PROGRAM_PULSE 37 #define OWERROR_READ_ONLY 38 #define OWERROR_NOT_GENERAL_PURPOSE 39 #define OWERROR_READ_BACK_INCORRECT 40 #define OWERROR_INVALID_PAGE_NUMBER 41 #define OWERROR_CRC_NOT_SUPPORTED 42 #define OWERROR_CRC_EXTRA_INFO_NOT_SUPPORTED 43 #define OWERROR_READ_BACK_NOT_VALID 44 #define OWERROR_COULD_NOT_LOCK_REDIRECT 45 #define OWERROR_READ_STATUS_NOT_COMPLETE 46 #define OWERROR_PAGE_REDIRECTION_NOT_SUPPORTED 47 #define OWERROR_LOCK_REDIRECTION_NOT_SUPPORTED 48 #define OWERROR_READBACK_EPROM_FAILED 49 #define OWERROR_PAGE_LOCKED 50 #define OWERROR_LOCKING_REDIRECTED_PAGE_AGAIN 51 #define OWERROR_REDIRECTED_PAGE 52 #define OWERROR_PAGE_ALREADY_LOCKED 53 #define OWERROR_WRITE_PROTECTED 54 #define OWERROR_NONMATCHING_MAC 55 #define OWERROR_WRITE_PROTECT 56 #define OWERROR_WRITE_PROTECT_SECRET 57 #define OWERROR_COMPUTE_NEXT_SECRET 58 #define OWERROR_LOAD_FIRST_SECRET 59 #define OWERROR_POWER_NOT_AVAILABLE 60 #define OWERROR_XBAD_FILENAME 61 #define OWERROR_XUNABLE_TO_CREATE_DIR 62 #define OWERROR_REPEAT_FILE 63 #define OWERROR_DIRECTORY_NOT_EMPTY 64 #define OWERROR_WRONG_TYPE 65 #define OWERROR_BUFFER_TOO_SMALL 66 #define OWERROR_NOT_WRITE_ONCE 67 #define OWERROR_FILE_NOT_FOUND 68 #define OWERROR_OUT_OF_SPACE 69 #define OWERROR_TOO_LARGE_BITNUM 70 #define OWERROR_NO_PROGRAM_JOB 71 #define OWERROR_FUNC_NOT_SUP 72 #define OWERROR_HANDLE_NOT_USED 73 #define OWERROR_FILE_WRITE_ONLY 74 #define OWERROR_HANDLE_NOT_AVAIL 75 #define OWERROR_INVALID_DIRECTORY 76 #define OWERROR_HANDLE_NOT_EXIST 77 #define OWERROR_NONMATCHING_SNUM 78 #define OWERROR_NON_PROGRAM_PARTS 79 #define OWERROR_PROGRAM_WRITE_PROTECT 80 #define OWERROR_FILE_READ_ERR 81 #define OWERROR_ADDFILE_TERMINATED 82 #define OWERROR_READ_MEMORY_PAGE_FAILED 83 #define OWERROR_MATCH_SCRATCHPAD_FAILED 84 #define OWERROR_ERASE_SCRATCHPAD_FAILED 85 #define OWERROR_READ_SCRATCHPAD_FAILED 86 #define OWERROR_SHA_FUNCTION_FAILED 87 #define OWERROR_NO_COMPLETION_BYTE 88 #define OWERROR_WRITE_DATA_PAGE_FAILED 89 #define OWERROR_COPY_SECRET_FAILED 90 #define OWERROR_BIND_SECRET_FAILED 91 #define OWERROR_INSTALL_SECRET_FAILED 92 #define OWERROR_VERIFY_SIG_FAILED 93 #define OWERROR_SIGN_SERVICE_DATA_FAILED 94 #define OWERROR_VERIFY_AUTH_RESPONSE_FAILED 95 #define OWERROR_ANSWER_CHALLENGE_FAILED 96 #define OWERROR_CREATE_CHALLENGE_FAILED 97 #define OWERROR_BAD_SERVICE_DATA 98 #define OWERROR_SERVICE_DATA_NOT_UPDATED 99 #define OWERROR_CATASTROPHIC_SERVICE_FAILURE 100 #define OWERROR_LOAD_FIRST_SECRET_FAILED 101 #define OWERROR_MATCH_SERVICE_SIGNATURE_FAILED 102 #endif //OWNET_H digitemp-3.6.0+dfsg1/userial/owerr.c0000644000175000017500000003066610632073746016017 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // owerr.c - Library functions for error handling with 1-Wire library // // Version: 1.00 // #include #ifndef _WIN32_WCE #include #endif #include "ownet.h" #ifndef SIZE_OWERROR_STACK #ifdef SMALL_MEMORY_TARGET //for small memory, only hole 1 error #define SIZE_OWERROR_STACK 1 #else #define SIZE_OWERROR_STACK 10 #endif #endif //--------------------------------------------------------------------------- // Variables //--------------------------------------------------------------------------- // Error Struct for holding error information. // In DEBUG, this will also hold the line number and filename. typedef struct { int owErrorNum; #ifdef DEBUG int lineno; char *filename; #endif } owErrorStruct; // Ring-buffer used for stack. // In case of overflow, deepest error is over-written. static owErrorStruct owErrorStack[SIZE_OWERROR_STACK]; // Stack pointer to top-most error. static int owErrorPointer = 0; //--------------------------------------------------------------------------- // Functions Definitions //--------------------------------------------------------------------------- int owGetErrorNum(void); void owClearError(void); int owHasErrors(void); #ifdef DEBUG void owRaiseError(int,int,char*); #else void owRaiseError(int); #endif #ifndef SMALL_MEMORY_TARGET void owPrintErrorMsg(FILE *); void owPrintErrorMsgStd(); char *owGetErrorMsg(int); #endif //-------------------------------------------------------------------------- // The 'owGetErroNum' returns the error code of the top-most error on the // error stack. NOTE: This function has the side effect of popping the // current error off the stack. All successive calls to 'owGetErrorNum' // will further clear the error stack. // // For list of error codes, see 'ownet.h' // // Returns: int : The error code of the top-most error on the stack // int owGetErrorNum(void) { int i = owErrorStack[ owErrorPointer ].owErrorNum; owErrorStack[ owErrorPointer ].owErrorNum = 0; if(!owErrorPointer) owErrorPointer = SIZE_OWERROR_STACK - 1; else owErrorPointer = (owErrorPointer - 1); return i; } //-------------------------------------------------------------------------- // The 'owClearError' clears all the errors. // void owClearError(void) { owErrorStack[ owErrorPointer ].owErrorNum = 0; } //-------------------------------------------------------------------------- // The 'owHasErrors' is a boolean test function which tests whether or not // a valid error is waiting on the stack. // // Returns: TRUE (1) : When there are errors on the stack. // FALSE (0): When stack's errors are set to 0, or NO_ERROR_SET. // int owHasErrors(void) { if(owErrorStack[ owErrorPointer ].owErrorNum) return 1; //TRUE else return 0; //FALSE } #ifdef DEBUG //-------------------------------------------------------------------------- // The 'owRaiseError' is the method for raising an error onto the error // stack. // // Arguments: int err - the error code you wish to raise. // int lineno - DEBUG only - the line number where it was raised // char* filename - DEBUG only - the file name where it occured. // void owRaiseError(int err, int lineno, char* filename) { owErrorPointer = (owErrorPointer + 1) % SIZE_OWERROR_STACK; owErrorStack[ owErrorPointer ].owErrorNum = err; owErrorStack[ owErrorPointer ].lineno = lineno; owErrorStack[ owErrorPointer ].filename = filename; } #else //-------------------------------------------------------------------------- // The 'owRaiseError' is the method for raising an error onto the error // stack. // // Arguments: int err - the error code you wish to raise. // void owRaiseError(int err) { owErrorPointer = (owErrorPointer + 1) % SIZE_OWERROR_STACK; owErrorStack[ owErrorPointer ].owErrorNum = err; } #endif // SMALL_MEMORY_TARGET - embedded microcontrollers, where these // messaging functions might not make any sense. #ifndef SMALL_MEMORY_TARGET //Array of meaningful error messages to associate with codes. //Not used on targets with low memory (i.e. PIC). static char *owErrorMsg[103] = { /*000*/ "No Error Was Set", /*001*/ "No Devices found on 1-Wire Network", /*002*/ "1-Wire Net Reset Failed", /*003*/ "Search ROM Error: Couldn't locate next device on 1-Wire", /*004*/ "Access Failed: Could not select device", /*005*/ "DS2480B Adapter Not Detected", /*006*/ "DS2480B: Wrong Baud", /*007*/ "DS2480B: Bad Response", /*008*/ "Open COM Failed", /*009*/ "Write COM Failed", /*010*/ "Read COM Failed", /*011*/ "Data Block Too Large", /*012*/ "Block Transfer failed", /*013*/ "Program Pulse Failed", /*014*/ "Program Byte Failed", /*015*/ "Write Byte Failed", /*016*/ "Read Byte Failed", /*017*/ "Write Verify Failed", /*018*/ "Read Verify Failed", /*019*/ "Write Scratchpad Failed", /*020*/ "Copy Scratchpad Failed", /*021*/ "Incorrect CRC Length", /*022*/ "CRC Failed", /*023*/ "Failed to acquire a necessary system resource", /*024*/ "Failed to initialize system resource", /*025*/ "Data too long to fit on specified device.", /*026*/ "Read exceeds memory bank end.", /*027*/ "Write exceeds memory bank end.", /*028*/ "Device select failed", /*029*/ "Read Scratch Pad verify failed.", /*030*/ "Copy scratchpad complete not found", /*031*/ "Erase scratchpad complete not found", /*032*/ "Address read back from scrachpad was incorrect", /*033*/ "Read page with extra-info not supported by this memory bank", /*034*/ "Read page packet with extra-info not supported by this memory bank", /*035*/ "Length of packet requested exceeds page size", /*036*/ "Invalid length in packet", /*037*/ "Program pulse required but not available", /*038*/ "Trying to access a read-only memory bank", /*039*/ "Current bank is not general purpose memory", /*040*/ "Read back from write compare is incorrect, page may be locked", /*041*/ "Invalid page number for this memory bank", /*042*/ "Read page with CRC not supported by this memory bank", /*043*/ "Read page with CRC and extra-info not supported by this memory bank", /*044*/ "Read back from write incorrect, could not lock page", /*045*/ "Read back from write incorrect, could not lock redirect byte", /*046*/ "The read of the status was not completed.", /*047*/ "Page redirection not supported by this memory bank", /*048*/ "Lock Page redirection not supported by this memory bank", /*049*/ "Read back byte on EPROM programming did not match.", /*050*/ "Can not write to a page that is locked.", /*051*/ "Can not lock a redirected page that has already been locked.", /*052*/ "Trying to redirect a locked redirected page.", /*053*/ "Trying to lock a page that is already locked.", /*054*/ "Trying to write to a memory bank that is write protected.", /*055*/ "Error due to not matching MAC.", /*056*/ "Memory Bank is write protected.", /*057*/ "Secret is write protected, can not Load First Secret.", /*058*/ "Error in Reading Scratchpad after Computing Next Secret.", /*059*/ "Load Error from Loading First Secret.", /*060*/ "Power delivery required but not available", /*061*/ "Not a valid file name.", /*062*/ "Unable to Create a Directory in this part.", /*063*/ "That file already exists.", /*064*/ "The directory is not empty.", /*065*/ "The wrong type of part for this operation.", /*066*/ "The max len for this file is too small.", /*067*/ "This is not a write once bank.", /*068*/ "The file can not be found.", /*069*/ "There is not enough space availabe.", /*070*/ "There is not a page to match that bit in the bitmap.", /*071*/ "There are no jobs for EPROM parts.", /*072*/ "Function not supported to modify attributes.", /*073*/ "Handle is not in use.", /*074*/ "Tring to read a write only file.", /*075*/ "There is no handle available for use.", /*076*/ "The directory provided is an invalid directory.", /*077*/ "Handle does not exist.", /*078*/ "Serial Number did not match with current job.", /*079*/ "Can not program EPROM because a non-EPROM part on the network.", /*080*/ "Write protect redirection byte is set.", /*081*/ "There is an inappropriate directory length.", /*082*/ "The file has already been terminated.", /*083*/ "Failed to read memory page of iButton part.", /*084*/ "Failed to match scratchpad of iButton part.", /*085*/ "Failed to erase scratchpad of iButton part.", /*086*/ "Failed to read scratchpad of iButton part.", /*087*/ "Failed to execute SHA function on SHA iButton.", /*088*/ "SHA iButton did not return a status completion byte.", /*089*/ "Write data page failed.", /*090*/ "Copy secret into secret memory pages failed.", /*091*/ "Bind unique secret to iButton failed.", /*092*/ "Could not install secret into user token.", /*093*/ "Transaction Incomplete: signature did not match.", /*094*/ "Transaction Incomplete: could not sign service data.", /*095*/ "User token did not provide a valid authentication response.", /*096*/ "Failed to answer a challenge on the user token.", /*097*/ "Failed to create a challenge on the coprocessor.", /*098*/ "Transaction Incomplete: service data was not valid.", /*099*/ "Transaction Incomplete: service data was not updated.", /*100*/ "Unrecoverable, catastrophic service failure occured.", /*101*/ "Load First Secret from scratchpad data failed.", /*102*/ "Failed to match signature of user's service data." }; char *owGetErrorMsg(int err) { return owErrorMsg[err]; } //-------------------------------------------------------------------------- // The 'owPrintErrorMsg' is the method for printing an error from the stack. // The destination for the print is specified by the argument, fileno, which // can be stderr, stdout, or a log file. In non-debug mode, the output is // of the form: // Error num: Error msg // // In debug-mode, the output is of the form: // Error num: filename line#: Error msg // // NOTE: This function has the side-effect of popping the error off the stack. // // Arguments: FILE*: the destination for printing. // void owPrintErrorMsg(FILE *fileno) { #ifdef DEBUG int l = owErrorStack[ owErrorPointer ].lineno; char *f = owErrorStack[ owErrorPointer ].filename; int err = owGetErrorNum(); fprintf(fileno,"Error %d: %s line %d: %s\r\n",err,f,l,owErrorMsg[err]); #else int err = owGetErrorNum(); fprintf(fileno,"Error %d: %s\r\n",err,owErrorMsg[err]); #endif } // Same as above, except uses default printf output void owPrintErrorMsgStd() { #ifdef DEBUG int l = owErrorStack[ owErrorPointer ].lineno; char *f = owErrorStack[ owErrorPointer ].filename; int err = owGetErrorNum(); printf("Error %d: %s line %d: %s\r\n",err,f,l,owErrorMsg[err]); #else int err = owGetErrorNum(); printf("Error %d: %s\r\n",err,owErrorMsg[err]); #endif } #endif digitemp-3.6.0+dfsg1/userial/ad26.c0000644000175000017500000002645311055426606015411 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //-------------------------------------------------------------------------- // // ad26.c - Reads the voltage on the 1-Wire // version 1.00 // // Include Files #include #include "ownet.h" #include "ad26.h" #include "owproto.h" extern int owBlock(int,int,uchar *,int); extern void setcrc8(int,uchar); extern uchar docrc8(int,uchar); extern int owReadByte(int); extern int owWriteByte(int,int); extern void output_status(int, char *); extern void msDelay(int); extern void owSerialNum(int,uchar *,int); extern int owAccess(int); int Volt_AD(int portnum, int vdd); float Volt_Reading(int portnum, int vdd, int *cad); double Get_Temperature(int portnum); int Volt_AD(int portnum, int vdd) { uchar send_block[50]; uchar test; int send_cnt=0; int i; ushort lastcrc8=255; int busybyte; /* 01/08/2004 [bcl] DigiTemp does this before calling the function * owSerialNum(portnum,SNum,FALSE); */ // Recall the Status/Configuration page // Recall command send_block[send_cnt++] = 0xB8; // Page to Recall send_block[send_cnt++] = 0x00; if(!owBlock(portnum,FALSE,send_block,send_cnt)) return FALSE; send_cnt = 0; if(owAccess(portnum)) { // Read the Status/Configuration byte // Read scratchpad command send_block[send_cnt++] = 0xBE; // Page for the Status/Configuration byte send_block[send_cnt++] = 0x00; for(i=0;i<9;i++) send_block[send_cnt++] = 0xFF; if(owBlock(portnum,FALSE,send_block,send_cnt)) { setcrc8(portnum,0); for(i=2;i> 3) * 0.03125; */ ret = ((((send_block[4] & 0x7F) << 8) | send_block[3]) >> 3); if( send_block[4] & 0x80 ) { /* Negative, take 2's complement and make it negative */ ret = -1 * (0x1000 - ret); } ret = ret * 0.03125; }//Access return ret; } /* ---- DS2406 PIO input by Tomasz R. Surmacz (tsurmacz@ict.pwr.wroc.pl) ---- */ int PIO_Reading(int portnum, int pionum /* TS ignored so far */ ) { uchar send_block[50]; int send_cnt=0; int i; short unsigned int infoByte, pioByte; ushort lastcrc16 = 0; int ret=0; int done = 3; // max tries if CRC error while (done-->0) { if(owAccess(portnum)) { // Recall the Status/Configuration page // Recall command send_block[send_cnt++] = 0xF5; // (b8) Channel access // Channel Control Byte 1 send_block[send_cnt++] = 0xCD; // ALR IM tog ic, CHS1 CHS0 crc1 CRC0 // CHS1 CHS0 = 01 = Channels A and B // ic: 0: asynchronous sampling, 1: synchronous // tog IM: 00: Write all bits to channel, 01: read all bits // ALR = 1 ==> reset activity latch // crc1crc0: 0: no crc, 1: after every byte, 2: every 8B, 3: 32B // Channel Control Byte 2 - reserved send_block[send_cnt++] = 0x00; // reserved if(!owBlock(portnum,FALSE,send_block,send_cnt)) return ret; // receive Channel Info Byte infoByte = (send_block[send_cnt++] = owReadByte(portnum)) & 0xff; // bit7: supply indication Vcc (0 = no supply) // bit6: no. of channels, 0 = channel A only // bit5: PIO-B activity latch // bit4: PIO-A activity latch // bit3: PIO-B sensed level // bit2: PIO-A sensed leve // bit1: PIO-B Channel Flip-Flop Q // bit0: PIO-A Channel Flip-Flop Q // Receive PIO Byte(s) until Master TX Reset pioByte = send_block[send_cnt++] = owReadByte(portnum); // read and check CRC setcrc16(portnum,0); for(i=0;i %04x (~%04x)\n", i, send_block[i], lastcrc16, lastcrc16 ^0xffff); } lastcrc16 ^= owReadByte(portnum); // CRC16, lsb lastcrc16 ^= (owReadByte(portnum) << 8); // CRC16, msb lastcrc16 ^= 0xffff; // DEBUG: // printf(" crc: %04x (~%04x)\n", lastcrc16, lastcrc16 ^0xffff); if(lastcrc16 != 0x0000) { printf("DS2406 crc error\n"); continue; } // reset bus and end reading PIO status owTouchReset(portnum); return ret=(infoByte <<8) + pioByte; // returns sampled data in LSB (bits 7-0), status byte in bits 15-8 // when reading both ports, (sampled bits are b3a3b2a2b1a1b0a0 or: // LSB should be 0x00 for A=0, B=0 // 0xAA for A=0, B=1 // 0x55 for A=1, B=0 // 0xFF for A=1, B=1 // status byte: 0x43 == 2-pio device, parasite powered, A=B=0 // 0x03 == 1-pio device, parasite powered // 0xC3, 0x83 - Vdd-powered, 2 or 1 pio device } // Access // printf(" DS2406 access error\n"); } // while(done) return -1; } digitemp-3.6.0+dfsg1/userial/ds2490/0000755000175000017500000000000011055620247015421 5ustar ryanryandigitemp-3.6.0+dfsg1/userial/ds2490/ownet.c0000644000175000017500000004547210632073746016743 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // ownet.C - Network functions for 1-Wire net devices. // // Version: 2.01 // // History: 1.00 -> 1.01 Change to owFamilySearchSetup, LastDiscrepancy[portnum] // was set to 64 instead of 8 to enable devices with // early contention to go in the '0' direction first. // 1.02 -> 1.03 Initialized goodbits in owVerify // 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for // multiple ports. // 2.00 -> 2.01 Added support for owError library // #include #include "ownet.h" #include "owproto.h" // External funcs extern SMALLINT owTouchBit(int,SMALLINT); extern SMALLINT owSpeed(int,SMALLINT); // exportable functions defined in ownet.c SMALLINT bitacc(SMALLINT,SMALLINT,SMALLINT,uchar *); // global variables for this module to hold search state information static SMALLINT LastDiscrepancy[MAX_PORTNUM]; static SMALLINT LastFamilyDiscrepancy[MAX_PORTNUM]; static SMALLINT LastDevice[MAX_PORTNUM]; uchar SerialNum[MAX_PORTNUM][8]; //-------------------------------------------------------------------------- // The 'owFirst' finds the first device on the 1-Wire Net This function // contains one parameter 'alarm_only'. When // 'alarm_only' 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. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'do_reset' - TRUE (1) perform reset before search, FALSE (0) do not // perform reset before search. // 'alarm_only' - 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[portnum] // FALSE (0): There are no devices on the 1-Wire Net. // SMALLINT owFirst(int portnum, SMALLINT do_reset, SMALLINT alarm_only) { // reset the search state LastDiscrepancy[portnum] = 0; LastDevice[portnum] = FALSE; LastFamilyDiscrepancy[portnum] = 0; return owNext(portnum,do_reset,alarm_only); } //-------------------------------------------------------------------------- // The 'owNext' function does a general search. This function // continues from the previos search state. The search state // can be reset by using the 'owFirst' function. // This function contains one parameter 'alarm_only'. // When 'alarm_only' 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. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'do_reset' - TRUE (1) perform reset before search, FALSE (0) do not // perform reset before search. // 'alarm_only' - 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[portnum] // FALSE (0): when no new device was found. Either the // last search was the last device or there // are no devices on the 1-Wire Net. // SMALLINT owNext(int portnum, SMALLINT do_reset, SMALLINT alarm_only) { uchar bit_test, search_direction, bit_number; uchar last_zero, serial_byte_number, next_result; uchar serial_byte_mask; uchar lastcrc8=0; // initialize for search bit_number = 1; last_zero = 0; serial_byte_number = 0; serial_byte_mask = 1; next_result = 0; setcrc8(portnum,0); // if the last call was not the last one if (!LastDevice[portnum]) { // check if reset first is requested if (do_reset) { // reset the 1-wire // if there are no parts on 1-wire, return FALSE if (!owTouchReset(portnum)) { // printf("owTouchReset failed\r\n"); // reset the search LastDiscrepancy[portnum] = 0; LastFamilyDiscrepancy[portnum] = 0; OWERROR(OWERROR_NO_DEVICES_ON_NET); return FALSE; } } // If finding alarming devices issue a different command if (alarm_only) owWriteByte(portnum,0xEC); // issue the alarming search command else owWriteByte(portnum,0xF0); // issue the search command //pause before beginning the search //usDelay(100); // loop to do the search do { // read a bit and its compliment bit_test = owTouchBit(portnum,1) << 1; bit_test |= owTouchBit(portnum,1); // check for no devices on 1-wire if (bit_test == 3) break; else { // all devices coupled have 0 or 1 if (bit_test > 0) search_direction = !(bit_test & 0x01); // bit write value for search else { // if this discrepancy if before the Last Discrepancy // on a previous next then pick the same as last time if (bit_number < LastDiscrepancy[portnum]) search_direction = ((SerialNum[portnum][serial_byte_number] & serial_byte_mask) > 0); else // if equal to last pick 1, if not then pick 0 search_direction = (bit_number == LastDiscrepancy[portnum]); // if 0 was picked then record its position in LastZero if (search_direction == 0) last_zero = bit_number; // check for Last discrepancy in family if (last_zero < 9) LastFamilyDiscrepancy[portnum] = last_zero; } // set or clear the bit in the SerialNum[portnum] byte serial_byte_number // with mask serial_byte_mask if (search_direction == 1) SerialNum[portnum][serial_byte_number] |= serial_byte_mask; else SerialNum[portnum][serial_byte_number] &= ~serial_byte_mask; // serial number search direction write bit owTouchBit(portnum,search_direction); // increment the byte counter bit_number // and shift the mask serial_byte_mask bit_number++; serial_byte_mask <<= 1; // if the mask is 0 then go to new SerialNum[portnum] byte serial_byte_number // and reset mask if (serial_byte_mask == 0) { lastcrc8 = docrc8(portnum,SerialNum[portnum][serial_byte_number]); // accumulate the CRC serial_byte_number++; serial_byte_mask = 1; } } } while(serial_byte_number < 8); // loop until through all SerialNum[portnum] bytes 0-7 // if the search was successful then if (!((bit_number < 65) || lastcrc8)) { // search successful so set LastDiscrepancy[portnum],LastDevice[portnum],next_result LastDiscrepancy[portnum] = last_zero; LastDevice[portnum] = (LastDiscrepancy[portnum] == 0); next_result = TRUE; } } // if no device found then reset counters so next 'next' will be // like a first if (!next_result || !SerialNum[portnum][0]) { LastDiscrepancy[portnum] = 0; LastDevice[portnum] = FALSE; LastFamilyDiscrepancy[portnum] = 0; next_result = FALSE; } return next_result; } //-------------------------------------------------------------------------- // The 'owSerialNum' function either reads or sets the SerialNum buffer // that is used in the search functions 'owFirst' and 'owNext'. // This function contains two parameters, 'serialnum_buf' is a pointer // to a buffer provided by the caller. 'serialnum_buf' should point to // an array of 8 unsigned chars. The second parameter is a flag called // 'do_read' 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. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'serialnum_buf' - buffer to that contains the serial number to set // when do_read = FALSE (0) and buffer to get the serial // number when do_read = TRUE (1). // 'do_read' - flag to indicate reading (1) or setting (0) the current // serial number. // void owSerialNum(int portnum, uchar *serialnum_buf, SMALLINT do_read) { uchar i; // read the internal buffer and place in 'serialnum_buf' if (do_read) { for (i = 0; i < 8; i++) serialnum_buf[i] = SerialNum[portnum][i]; } // set the internal buffer from the data in 'serialnum_buf' else { for (i = 0; i < 8; i++) SerialNum[portnum][i] = serialnum_buf[i]; } } //-------------------------------------------------------------------------- // Setup the search algorithm to find a certain family of devices // the next time a search function is called 'owNext'. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'search_family' - family code type to set the search algorithm to find // next. // void owFamilySearchSetup(int portnum, SMALLINT search_family) { uchar i; // set the search state to find SearchFamily type devices SerialNum[portnum][0] = search_family; for (i = 1; i < 8; i++) SerialNum[portnum][i] = 0; LastDiscrepancy[portnum] = 64; LastDevice[portnum] = FALSE; } //-------------------------------------------------------------------------- // Set the current search state to skip the current family code. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // void owSkipFamily(int portnum) { // set the Last discrepancy to last family discrepancy LastDiscrepancy[portnum] = LastFamilyDiscrepancy[portnum]; // check for end of list if (LastDiscrepancy[portnum] == 0) LastDevice[portnum] = TRUE; } //-------------------------------------------------------------------------- // The 'owAccess' 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. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // // 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. // SMALLINT owAccess(int portnum) { uchar sendpacket[9]; uchar i; // reset the 1-wire if (owTouchReset(portnum)) { // create a buffer to use with block function // match Serial Number command 0x55 sendpacket[0] = 0x55; // Serial Number for (i = 1; i < 9; i++) sendpacket[i] = SerialNum[portnum][i-1]; // send/recieve the transfer buffer if (owBlock(portnum,FALSE,sendpacket,9)) { // verify that the echo of the writes was correct for (i = 1; i < 9; i++) if (sendpacket[i] != SerialNum[portnum][i-1]) return FALSE; if (sendpacket[0] != 0x55) { OWERROR(OWERROR_WRITE_VERIFY_FAILED); return FALSE; } else return TRUE; } else OWERROR(OWERROR_BLOCK_FAILED); } else OWERROR(OWERROR_NO_DEVICES_ON_NET); // reset or match echo failed return FALSE; } //---------------------------------------------------------------------- // The function 'owVerify' verifies that the current device // is in contact with the 1-Wire Net. // Using the find alarm command 0xEC will verify that the device // is in contact with the 1-Wire Net and is in an 'alarm' state. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'alarm_only' - 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 1-Wire Net // with alarm_only == FALSE // or verified to be on the 1-Wire Net // AND in an alarm state when // alarm_only == TRUE. // FALSE (0): the 1-Wire device was not on the // 1-Wire Net or if alarm_only // == TRUE, the device may be on the // 1-Wire Net but in a non-alarm state. // SMALLINT owVerify(int portnum, SMALLINT alarm_only) { uchar i,sendlen=0,goodbits=0,cnt=0,s,tst; uchar sendpacket[50]; // construct the search if (alarm_only) sendpacket[sendlen++] = 0xEC; // issue the alarming search command else sendpacket[sendlen++] = 0xF0; // issue the search command // set all bits at first for (i = 1; i <= 24; i++) sendpacket[sendlen++] = 0xFF; // now set or clear apropriate bits for search for (i = 0; i < 64; i++) bitacc(WRITE_FUNCTION,bitacc(READ_FUNCTION,0,i,&SerialNum[portnum][0]),(int)((i+1)*3-1),&sendpacket[1]); // send/recieve the transfer buffer if (owBlock(portnum,TRUE,sendpacket,sendlen)) { // check results to see if it was a success for (i = 0; i < 192; i += 3) { tst = (bitacc(READ_FUNCTION,0,i,&sendpacket[1]) << 1) | bitacc(READ_FUNCTION,0,(int)(i+1),&sendpacket[1]); s = bitacc(READ_FUNCTION,0,cnt++,&SerialNum[portnum][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; } else OWERROR(OWERROR_BLOCK_FAILED); // 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. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // // Returns: TRUE: If the device is present on the 1-Wire Net 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. // SMALLINT owOverdriveAccess(int portnum) { uchar sendpacket[8]; uchar i, bad_echo = FALSE; // make sure normal level owLevel(portnum,MODE_NORMAL); // force to normal communication speed owSpeed(portnum,MODE_NORMAL); // call the 1-Wire Net reset function if (owTouchReset(portnum)) { // send the match command 0x69 if (owWriteByte(portnum,0x69)) { // switch to overdrive communication speed owSpeed(portnum,MODE_OVERDRIVE); // create a buffer to use with block function // Serial Number for (i = 0; i < 8; i++) sendpacket[i] = SerialNum[portnum][i]; // send/recieve the transfer buffer if (owBlock(portnum,FALSE,sendpacket,8)) { // verify that the echo of the writes was correct for (i = 0; i < 8; i++) if (sendpacket[i] != SerialNum[portnum][i]) bad_echo = TRUE; // if echo ok then success if (!bad_echo) return TRUE; else OWERROR(OWERROR_WRITE_VERIFY_FAILED); } else OWERROR(OWERROR_BLOCK_FAILED); } else OWERROR(OWERROR_WRITE_BYTE_FAILED); } else OWERROR(OWERROR_NO_DEVICES_ON_NET); // failure, force back to normal communication speed owSpeed(portnum,MODE_NORMAL); return FALSE; } //-------------------------------------------------------------------------- // 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 // SMALLINT bitacc(SMALLINT op, SMALLINT state, SMALLINT loc, uchar *buf) { SMALLINT 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); } digitemp-3.6.0+dfsg1/userial/ds2490/owtran.c0000644000175000017500000001461310632073746017112 0ustar ryanryan//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // owTran.C - Transport functions for 1-Wire devices. // // Version: 2.01 // // History: 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for // multiple ports. // 2.00 -> 2.01 Added support for owError library // #include "ownet.h" #include "owproto.h" //-------------------------------------------------------------------------- // The 'owBlock' transfers a block of data to and from the // 1-Wire Net with an optional reset at the begining of communication. // The result is returned in the same buffer. // // 'do_reset' - cause a owTouchReset to occure at the begining of // communication TRUE(1) or not FALSE(0) // 'tran_buf' - pointer to a block of unsigned // chars of length 'TranferLength' that will be sent // to the 1-Wire Net // 'tran_len' - length in bytes to transfer // Supported devices: all // // Returns: TRUE (1) : The optional reset returned a valid // presence (do_reset == TRUE) or there // was no reset required. // FALSE (0): The reset did not return a valid prsence // (do_reset == TRUE). // // The maximum tran_len is 160 // SMALLINT owBlock(int portnum, SMALLINT do_reset, uchar *tran_buf, SMALLINT tran_len) { uchar i; // check for a block too big if (tran_len > 160) { OWERROR(OWERROR_BLOCK_TOO_BIG); return FALSE; } // check if need to do a owTouchReset first if (do_reset) { if (!owTouchReset(portnum)) { OWERROR(OWERROR_NO_DEVICES_ON_NET); return FALSE; } } // send and receive the buffer for (i = 0; i < tran_len; i++) tran_buf[i] = (uchar)owTouchByte(portnum,tran_buf[i]); return TRUE; } //-------------------------------------------------------------------------- // Write a byte to an EPROM 1-Wire device. // // Supported devices: crc_type=0(CRC8) // DS1982 // crc_type=1(CRC16) // DS1985, DS1986, DS2407 // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'write_byte' - byte to program // 'addr' - address of byte to program // 'write_cmd' - command used to write (0x0F reg mem, 0x55 status) // 'crc_type' - CRC used (0 CRC8, 1 CRC16) // 'do_access' - Flag to access device for each byte // (0 skip access, 1 do the access) // WARNING, only use do_access=0 if programing the NEXT // byte immediatly after the previous byte. // // Returns: >=0 success, this is the resulting byte from the program // effort // -1 error, device not connected or program pulse voltage // not available // SMALLINT owProgramByte(int portnum, SMALLINT write_byte, int addr, SMALLINT write_cmd, SMALLINT crc_type, SMALLINT do_access) { ushort lastcrc16; uchar lastcrc8; // optionally access the device if (do_access) { if (!owAccess(portnum)) { OWERROR(OWERROR_ACCESS_FAILED); return -1; } // send the write command if (!owWriteByte(portnum,write_cmd)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return -1; } // send the address if (!owWriteByte(portnum,addr & 0xFF) || !owWriteByte(portnum,addr >> 8)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return -1; } } // send the data to write if (!owWriteByte(portnum,write_byte)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return -1; } // read the CRC if (crc_type == 0) { // calculate CRC8 if (do_access) { setcrc8(portnum,0); docrc8(portnum,(uchar)write_cmd); docrc8(portnum,(uchar)(addr & 0xFF)); docrc8(portnum,(uchar)(addr >> 8)); } else setcrc8(portnum,(uchar)(addr & 0xFF)); docrc8(portnum,(uchar)write_byte); // read and calculate the read crc lastcrc8 = docrc8(portnum,(uchar)owReadByte(portnum)); // crc should now be 0x00 if (lastcrc8 != 0) { OWERROR(OWERROR_CRC_FAILED); return -1; } } else { // CRC16 if (do_access) { setcrc16(portnum,0); docrc16(portnum,(ushort)write_cmd); docrc16(portnum,(ushort)(addr & 0xFF)); docrc16(portnum,(ushort)(addr >> 8)); } else setcrc16(portnum,(ushort)addr); docrc16(portnum,(ushort)write_byte); // read and calculate the read crc docrc16(portnum,(ushort)owReadByte(portnum)); lastcrc16 = docrc16(portnum,(ushort)owReadByte(portnum)); // crc should now be 0xB001 if (lastcrc16 != 0xB001) return -1; } // send the program pulse if (!owProgramPulse(portnum)) { OWERROR(OWERROR_PROGRAM_PULSE_FAILED); return -1; } // read back and return the resulting byte return owReadByte(portnum); } digitemp-3.6.0+dfsg1/userial/ds2490/usblnk.h0000644000175000017500000000123410632073746017076 0ustar ryanryan #define CONTROL_CMD 0x00 #define COMM_CMD 0x01 #define MODE_CMD 0x02 #define TEST_CMD 0x03 #define CTL_RESET_DEVICE 0x0000 #define CTL_START_EXE 0x0001 #define CTL_RESUME_EXE 0x0002 #define CTL_HALT_EXE_IDLE 0x0003 #define CTL_HALT_EXE_DONE 0x0004 #define CTL_FLUSH_COMM_CMDS 0x0007 #define CTL_FLUSH_CV_BUFFER 0x0008 #define CTL_FLUSH_CMT_BUFFER 0x0009 #define CTL_GET_COMM_CMDS 0x000A #define MOD_PULSE_EN 0x0000 #define MOD_SPEED_CHANGE_EN 0x0001 #define MOD_1WIRE_SPEED 0x0002 #define MOD_STRONG_PU_DURATION 0x0003 #define MOD_PULLDOWN_SLEWRATE 0x0004 #define MOD_PROG_PULSE_DURATION 0x0005 #define MOD_WRITE1_LOWTIME 0x0006 #define MOD_DSOW0_TREC 0x0007 digitemp-3.6.0+dfsg1/userial/ds2490/usblnk.c0000644000175000017500000003653111055430035017065 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2001 Matthew Dharm, 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. // // Matthew is not activily supporting this code but can be reached at: // mailto:mdharm-usb@one-eyed-alien.net //--------------------------------------------------------------------------- // // usb_drv.c - General 1-Wire link layer for the DS2490 on Linux // // // Version: 3.00B // // // 3.00 -> 3.10: bcl Implemented strong pullup and program pulse // support that was keeping it from working // correctly using owWriteBytePower() // #include "ownet.h" #include "usb.h" #include #include #include "usblnk.h" /* wrap in Linux? */ #include /* Wrap in Linux? */ #define TIMEOUT_VALUE 5000 /* the structure we'll use to access other devices */ extern struct usb_dev_handle *usb_dev_handle_list[MAX_PORTNUM]; // exportable link-level functions SMALLINT owTouchReset(int); SMALLINT owTouchBit(int,SMALLINT); SMALLINT owTouchByte(int,SMALLINT); SMALLINT owWriteByte(int,SMALLINT); SMALLINT owReadByte(int); SMALLINT owSpeed(int,SMALLINT); SMALLINT owLevel(int,SMALLINT); SMALLINT owProgramPulse(int); void msDelay(int); long msGettick(void); SMALLINT hasPowerDelivery(int); SMALLINT hasOverDrive(int); SMALLINT hasProgramPulse(int); SMALLINT owWriteBytePower(int,SMALLINT); SMALLINT owReadBitPower(int, SMALLINT); //-------------------------------------------------------------------------- // Reset all of the devices on the 1-Wire Net and return the result. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // // Returns: TRUE(1): presense pulse(s) detected, device(s) reset // FALSE(0): no presense pulses detected // int owTouchReset(int portnum) { int result; char buffer[0x20]; /* issue the 1-wire reset */ result = usb_control_msg(usb_dev_handle_list[portnum], 0x40, COMM_CMD, 0x0043, 0x0000, NULL, 0x0, TIMEOUT_VALUE); //printf("result is %d\n", result); /* repeat until the unit is not idle */ do { /* get the status */ result = usb_bulk_read(usb_dev_handle_list[portnum], 0x81, buffer, 0x20, TIMEOUT_VALUE); //printf("result is %d\n", result); //for (result = 0; result < 0x20; result++) { // printf("%02X: %02X\n", result, buffer[result]); //} } while (!(buffer[0x08] & 0x20) && !(result < 0)); if (result < 0) return FALSE; if (buffer[0x10] & 0x01) { return FALSE; } else { return TRUE; } } //-------------------------------------------------------------------------- // Send 1 bit of communication to the 1-Wire Net and return the // result 1 bit read from the 1-Wire Net. The parameter 'sendbit' // least significant bit is used and the least significant bit // of the result is the return bit. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'sendbit' - the least significant bit is the bit to send // // Returns: 0: 0 bit read from sendbit // 1: 1 bit read from sendbit // int owTouchBit(int portnum, SMALLINT sendbit) { int result; char retval; char buffer[0x20]; /* issue the bit i/o command */ result = usb_control_msg(usb_dev_handle_list[portnum], 0x40, COMM_CMD, 0x0021 | (sendbit << 3), 0x0000, NULL, 0x0, TIMEOUT_VALUE); //printf("result is %d\n", result); /* repeat until the unit is not idle */ do { /* get the status */ result = usb_bulk_read(usb_dev_handle_list[portnum], 0x81, buffer, 0x20, TIMEOUT_VALUE); //printf("result is %d\n", result); //for (result = 0; result < 0x20; result++) { // printf("%02X: %02X\n", result, buffer[result]); //} } while (!(buffer[0x08] & 0x20) && !(result < 0)); /* get the data */ result = usb_bulk_read(usb_dev_handle_list[portnum], 0x83, &retval, 0x1, 1000); if (result == -1) { printf ("owTouchBit: clearing halt\n"); usb_clear_halt(usb_dev_handle_list[portnum], 0x83); } /* return the data */ return retval; } //-------------------------------------------------------------------------- // Send 8 bits of communication to the 1-Wire Net and return the // result 8 bits read from the 1-Wire Net. The parameter 'sendbyte' // least significant 8 bits are used and the least significant 8 bits // of the result is the return byte. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'sendbyte' - 8 bits to send (least significant byte) // // Returns: 8 bytes read from sendbyte // int owTouchByte(int portnum, SMALLINT sendbyte) { int result; char retval; char buffer[0x20]; /* issue the byte i/o command */ result = usb_control_msg(usb_dev_handle_list[portnum], 0x40, COMM_CMD, 0x0053, 0x0000 | sendbyte, NULL, 0x0, TIMEOUT_VALUE); //printf("result is %d\n", result); /* repeat until the unit is not idle */ do { /* get the status */ result = usb_bulk_read(usb_dev_handle_list[portnum], 0x81, buffer, 0x20, TIMEOUT_VALUE); //printf("result is %d\n", result); //for (result = 0; result < 0x20; result++) { // printf("%02X: %02X\n", result, buffer[result]); //} } while (!(buffer[0x08] & 0x20) && !(result < 0)); /* get the data */ result = usb_bulk_read(usb_dev_handle_list[portnum], 0x83, &retval, 0x1, 1000); if (result == -1) { printf ("owTouchByte: clearing halt\n"); usb_clear_halt(usb_dev_handle_list[portnum], 0x83); } /* return the data */ return retval; } //-------------------------------------------------------------------------- // Send 8 bits of communication to the 1-Wire Net and verify that the // 8 bits read from the 1-Wire Net is the same (write operation). // The parameter 'sendbyte' least significant 8 bits are used. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'sendbyte' - 8 bits to send (least significant byte) // // Returns: TRUE: bytes written and echo was the same // FALSE: echo was not the same // int owWriteByte(int portnum, SMALLINT sendbyte) { return (owTouchByte(portnum,sendbyte) == sendbyte) ? TRUE : FALSE; } //-------------------------------------------------------------------------- // Send 8 bits of read communication to the 1-Wire Net and and return the // result 8 bits read from the 1-Wire Net. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // // Returns: 8 bytes read from 1-Wire Net // int owReadByte(int portnum) { return owTouchByte(portnum,0xFF); } //-------------------------------------------------------------------------- // Set the 1-Wire Net communucation speed. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'new_speed' - new speed defined as // MODE_NORMAL 0x00 // MODE_OVERDRIVE 0x01 // // Returns: current 1-Wire Net speed // int owSpeed(int portnum, SMALLINT new_speed) { int result; char buffer[0x20]; /* issue the command to enable speed changes */ result = usb_control_msg(usb_dev_handle_list[portnum], 0x40, MODE_CMD, MOD_SPEED_CHANGE_EN, 0x0001, NULL, 0x0, TIMEOUT_VALUE); //printf("result is %d\n", result); /* repeat until the unit is not idle */ do { /* get the status */ result = usb_bulk_read(usb_dev_handle_list[portnum], 0x81, buffer, 0x20, TIMEOUT_VALUE); //printf("result is %d\n", result); //for (result = 0; result < 0x20; result++) { // printf("%02X: %02X\n", result, buffer[result]); //} } while (!(buffer[0x08] & 0x20) && !(result < 0)); /* issue the command to change the speed */ result = usb_control_msg(usb_dev_handle_list[portnum], 0x40, MODE_CMD, MOD_1WIRE_SPEED, new_speed ? 0x0002 : 0x0000, NULL, 0x0, TIMEOUT_VALUE); //printf("result is %d\n", result); /* repeat until the unit is not idle */ do { /* get the status */ result = usb_bulk_read(usb_dev_handle_list[portnum], 0x81, buffer, 0x20, TIMEOUT_VALUE); //printf("result is %d\n", result); //for (result = 0; result < 0x20; result++) { // printf("%02X: %02X\n", result, buffer[result]); //} } while (!(buffer[0x08] & 0x20) && !(result < 0)); /* return the data */ return new_speed; } //-------------------------------------------------------------------------- // Set the 1-Wire Net line level. The values for NewLevel are // as follows: // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'new_level' - new level defined as // MODE_NORMAL 0x00 // MODE_STRONG5 0x02 // MODE_PROGRAM 0x04 // MODE_BREAK 0x08 // // Returns: current 1-Wire Net level // int owLevel(int portnum, SMALLINT new_level) { int result; char buffer[0x20]; unsigned int pulse; switch( new_level ) { case MODE_NORMAL: pulse = 0x0000; break; case MODE_STRONG5: pulse = 0x0002; break; case MODE_PROGRAM: pulse = 0x0001; break; default: pulse = 0x0000; break; } /* issue the command to enable speed changes */ result = usb_control_msg(usb_dev_handle_list[portnum], 0x40, MODE_CMD, MOD_PULSE_EN, pulse, NULL, 0x0, TIMEOUT_VALUE); //printf("result is %d\n", result); /* repeat until the unit is not idle */ do { /* get the status */ result = usb_bulk_read(usb_dev_handle_list[portnum], 0x81, buffer, 0x20, TIMEOUT_VALUE); //printf("result is %d\n", result); //for (result = 0; result < 0x20; result++) { // printf("%02X: %02X\n", result, buffer[result]); //} } while (!(buffer[0x08] & 0x20) && !(result < 0)); /* return the data */ return (result < 0) ? result : new_level; } //-------------------------------------------------------------------------- // This procedure creates a fixed 480 microseconds 12 volt pulse // on the 1-Wire Net for programming EPROM iButtons. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // // Returns: TRUE successful // FALSE program voltage not available // int owProgramPulse(int portnum) { // Adapter supports it but not implemented yet return 0; } //-------------------------------------------------------------------------- // 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); } //-------------------------------------------------------------------------- // 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; } //-------------------------------------------------------------------------- // Send 8 bits of communication to the 1-Wire Net and verify that the // 8 bits read from the 1-Wire Net is the same (write operation). // The parameter 'sendbyte' least significant 8 bits are used. After the // 8 bits are sent change the level of the 1-Wire net. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'sendbyte' - 8 bits to send (least significant byte) // // Returns: TRUE: bytes written and echo was the same // FALSE: echo was not the same // SMALLINT owWriteBytePower(int portnum, SMALLINT sendbyte) { // replace if platform has better implementation (faster response) if (!hasPowerDelivery(portnum)) return FALSE; if(owTouchByte(portnum,sendbyte) != sendbyte) return FALSE; if(owLevel(portnum,MODE_STRONG5) != MODE_STRONG5) return FALSE; return TRUE; } //-------------------------------------------------------------------------- // Send 1 bit of communication to the 1-Wire Net and verify that the // response matches the 'applyPowerResponse' bit and apply power delivery // to the 1-Wire net. Note that some implementations may apply the power // first and then turn it off if the response is incorrect. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'applyPowerResponse' - 1 bit response to check, if correct then start // power delivery // // Returns: TRUE: bit written and response correct, strong pullup now on // FALSE: response incorrect // SMALLINT owReadBitPower(int portnum, SMALLINT applyPowerResponse) { // replace if platform has better implementation (faster response) if (!hasPowerDelivery(portnum)) return FALSE; if(owTouchBit(portnum,0x01) != applyPowerResponse) return FALSE; if(owLevel(portnum,MODE_STRONG5) != MODE_STRONG5) return FALSE; return TRUE; } //-------------------------------------------------------------------------- // This procedure indicates wether the adapter can deliver power. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE if adapter is capable of delivering power. // SMALLINT hasPowerDelivery(int portnum) { // Implemented by bcl@brianlane.com return TRUE; } //-------------------------------------------------------------------------- // This procedure indicates wether the adapter can deliver power. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE if adapter is capable of over drive. // SMALLINT hasOverDrive(int portnum) { return TRUE; } //-------------------------------------------------------------------------- // This procedure creates a fixed 480 microseconds 12 volt pulse // on the 1-Wire Net for programming EPROM iButtons. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE program volatage available // FALSE program voltage not available SMALLINT hasProgramPulse(int portnum) { // Implemented by bcl@brianlane.com return TRUE; } digitemp-3.6.0+dfsg1/userial/ds2490/usbses.c0000644000175000017500000001255711055427777017120 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2001 Matthew Dharm, 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. // // Matthew is not activily supporting this code but can be reached at: // mailto:mdharm-usb@one-eyed-alien.net //--------------------------------------------------------------------------- // // usb_sessuin.c - General 1-Wire session layer for the DS2490 on Linux // // Version: 3.00B // #include "ownet.h" #include #include #include "digitemp.h" SMALLINT owAcquire(int,char *, char *); void owRelease(int,char *); static void usb_ds2490_init(void); struct usb_dev_handle *usb_dev_handle_list[MAX_PORTNUM]; struct usb_device *usb_dev_list[MAX_PORTNUM]; int usb_num_devices = -1; int initted_flag = 0; extern int opts; // Command line options //--------------------------------------------------------------------------- // Initialize the DS2490 // void usb_ds2490_init(void) { struct usb_bus *bus; struct usb_device *dev; // initialize USB subsystem usb_init(); usb_set_debug(0); usb_find_busses(); usb_find_devices(); //printf("bus/device idVendor/idProduct\n"); for (bus = usb_busses; bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) { //printf("%s/%s %04X/%04X\n", bus->dirname, dev->filename, // dev->descriptor.idVendor, dev->descriptor.idProduct); if (dev->descriptor.idVendor == 0x04FA && dev->descriptor.idProduct == 0x2490) { ++usb_num_devices; usb_dev_list[usb_num_devices] = dev; if( !(opts & OPT_QUIET) ) printf("Found DS2490 device #%d at %s/%s\n", usb_num_devices + 1, bus->dirname, dev->filename); } } } initted_flag = 1; } //--------------------------------------------------------------------------- // Attempt to acquire a 1-Wire net // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'port_zstr' - zero terminated port name. // 'return_msg' - zero terminated return message. // // Returns: TRUE - success, port opened // SMALLINT owAcquire(int portnum, char *port_zstr, char *return_msg) { if (!initted_flag) usb_ds2490_init(); /* check the port string */ if (strcmp (port_zstr, "USB")) { strcpy(return_msg, "owAcquire called with invalid port string\n"); return 0; } /* check to see if the portnumber is valid */ if (usb_num_devices < portnum) { strcpy(return_msg, "Attempted to select invalid port number\n"); return FALSE; } /* check to see if opening the device is valid */ if (usb_dev_handle_list[portnum] != NULL) { strcpy(return_msg, "Device allready open\n"); return FALSE; } /* open the device */ usb_dev_handle_list[portnum] = usb_open(usb_dev_list[portnum]); if (usb_dev_handle_list[portnum] == NULL) { strcpy(return_msg, "Failed to open usb device\n"); printf("%s\n", usb_strerror()); return FALSE; } /* set the configuration */ if (usb_set_configuration(usb_dev_handle_list[portnum], 1)) { strcpy(return_msg, "Failed to set configuration\n"); printf("%s\n", usb_strerror()); usb_close(usb_dev_handle_list[portnum]); return FALSE; } /* claim the interface */ if (usb_claim_interface(usb_dev_handle_list[portnum], 0)) { strcpy(return_msg, "Failed to claim interface\n"); printf("%s\n", usb_strerror()); usb_close(usb_dev_handle_list[portnum]); return FALSE; } /* set the alt interface */ if (usb_set_altinterface(usb_dev_handle_list[portnum], 3)) { strcpy(return_msg, "Failed to set altinterface\n"); printf("%s\n", usb_strerror()); usb_release_interface(usb_dev_handle_list[portnum], 0); usb_close(usb_dev_handle_list[portnum]); return FALSE; } /* we're all set here! */ strcpy(return_msg, "DS2490 successfully acquired by USB driver\n"); return TRUE; } //--------------------------------------------------------------------------- // Release the previously acquired a 1-Wire net. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'return_msg' - zero terminated return message. // void owRelease(int portnum, char *return_msg) { usb_release_interface(usb_dev_handle_list[portnum], 0); usb_close(usb_dev_handle_list[portnum]); usb_dev_handle_list[portnum] = NULL; strcpy(return_msg, "DS2490 successfully released by USB driver\n"); } digitemp-3.6.0+dfsg1/userial/ds9097/0000755000175000017500000000000011055620247015433 5ustar ryanryandigitemp-3.6.0+dfsg1/userial/ds9097/linuxses.c0000644000175000017500000001031110632073746017453 0ustar ryanryan/* Copyright (c) 2003, Erik Rigtorp * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Erik Rigtorp nor the names of his contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * * linuxses.c (0.20) * * * Cleaned up everything. * * * Added printing of error messages. * * -- Erik Rigtorp Thu, 05 Jun 2003 00:57:44 +0200 */ #include #include #include #include /* local function prototypes */ SMALLINT owAcquire(int,char *); void owRelease(int); int fd[MAX_PORTNUM]; /* a list of filedescriptors for serial ports */ struct termios term[MAX_PORTNUM]; /* Current termios settings */ struct termios term_orig[MAX_PORTNUM]; /* backup termios settings */ /* Attempt to acquire a 1-Wire net. Associate 'portnum' with the serial port * with name 'port_zstr'. Returns TRUE on success. */ SMALLINT owAcquire(int portnum, char *port_zstr) { /* Open the serial port */ if ((fd[portnum] = open(port_zstr, O_RDWR)) == -1) { OWERROR(OWERROR_GET_SYSTEM_RESOURCE_FAILED); perror("owAcquire: failed to open device"); return FALSE; } /* Get device settings */ if(tcgetattr(fd[portnum], &term[portnum] ) < 0 ) { OWERROR(OWERROR_SYSTEM_RESOURCE_INIT_FAILED); perror("owAcquire: failed to set attributes"); close(fd[portnum]); return FALSE; } /* Save a backup */ term_orig[portnum] = term[portnum]; /* Reset all settings */ term[portnum].c_iflag = 0; term[portnum].c_oflag = 0; term[portnum].c_lflag = 0; term[portnum].c_cflag = 0; /* 1 byte at a time, no timer */ term[portnum].c_cc[VMIN] = 1; term[portnum].c_cc[VTIME] = 0; /* 6 data bits, Receiver enabled, Hangup, Dont change "owner" */ term[portnum].c_cflag |= CS6 | CREAD | HUPCL | CLOCAL; /* Set input and output speed to 115.2k */ cfsetispeed(&term[portnum], B115200); cfsetospeed(&term[portnum], B115200); /* set the attributes */ if(tcsetattr(fd[portnum], TCSANOW, &term[portnum]) < 0 ) { OWERROR(OWERROR_SYSTEM_RESOURCE_INIT_FAILED); perror("owAcquire: failed to set attributes"); close(fd[portnum]); return FALSE; } /* Flush the input and output buffers */ tcflush(fd[portnum], TCIOFLUSH); return TRUE; } /* Release port 'portnum' */ void owRelease(int portnum) { /* Restore original settings */ if(tcsetattr(fd[portnum], TCSANOW, &term_orig[portnum]) < 0 ) { /* We failed doing that */ OWERROR(OWERROR_SYSTEM_RESOURCE_INIT_FAILED); perror("owAcquire: failed to set attributes"); close(fd[portnum]); } /* Close the port */ if (close(fd[portnum]) < 0) { /* We failed closing the port */ OWERROR(OWERROR_SYSTEM_RESOURCE_INIT_FAILED); perror("owAcquire: failed to close port"); } /* we should return an error condition here but MAXIMS API is * badly designed */ } digitemp-3.6.0+dfsg1/userial/ds9097/linuxlnk.c0000644000175000017500000003567510632073746017471 0ustar ryanryan/* Copyright (c) 2003, Erik Rigtorp * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Erik Rigtorp nor the names of his contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * * linuxlnk.c (0.21) * * * Fixed strong pullup return codes so that it doesn't make higer level * code fail when owLevel is used. It returns the value it is called * with. * * -- Brian Lane 2/3/2004 * * linuxlnk.c (0.20) * * * Cleaned up this mess. * * * Added lots of comments. * * -- Erik Rigtorp Thu, 05 Jun 2003 15:07:08 +0200 * * linuxlnk.c (0.13) * * * Incorporated changes from Jari Kirma . These * changes improves performace several times. By using the UARTs * FIFO it sends several bits of data to the network and then reads * the result. My old code sent one bit and read one bit at a time. * Thanks Jari! * * -- Erik Rigtorp Thu, 05 Jun 2003 00:57:44 +0200 * * linuxlnk.c (0.10) * * * First working implementation, derived from work by Brian C. Lane. * * -- Erik Rigtorp Unknown * */ #include #include #include #include #include #include #ifdef LINUX #include #endif #include /* The UART_FIFO_SIZE defines the amount of bytes that are written before * reading the reply. Any positive value should work and 16 is probably low * enough to avoid losing bytes in even most extreme situations on all modern * UARTs, and values bigger than that will probably work on almost any * system... The value affects readout performance asymptotically, value of 1 * should give equivalent performance with the old implementation. * -- Jari Kirma * * Note: Each bit sent to the 1-wire net requeires 1 byte to be sent to * the uart. */ #define UART_FIFO_SIZE 160 #define TIMEOUT 5 /* exportable link-level functions */ SMALLINT owTouchReset(int); SMALLINT owTouchBit(int,SMALLINT); SMALLINT owTouchByte(int,SMALLINT); SMALLINT owWriteByte(int,SMALLINT); SMALLINT owReadByte(int); SMALLINT owSpeed(int,SMALLINT); SMALLINT owLevel(int,SMALLINT); SMALLINT owProgramPulse(int); void msDelay(int); long msGettick(void); SMALLINT hasPowerDelivery(int); SMALLINT hasOverDrive(int); SMALLINT hasProgramPulse(int); SMALLINT owWriteBytePower(int,SMALLINT); SMALLINT owReadBitPower(int, SMALLINT); extern int fd[MAX_PORTNUM]; /* Reset all of the devices on the 1-Wire Net and return the result. Returns * TRUE if presense pulse(s) was detected and devices(s) reset, otherwise * the reset has failed and it returns FALSE. */ SMALLINT owTouchReset(int portnum) { fd_set readset; struct timeval timeout_tv; int stat = 0; unsigned char wbuff; unsigned char result = 0; //extern int global_msec, global_msec_max; extern struct termios term[MAX_PORTNUM]; /* Flush the input and output buffers */ tcflush(fd[portnum], TCIOFLUSH); /* 8 data bits */ term[portnum].c_cflag |= CS8; /* Set input and output speed to 9.6k */ cfsetispeed(&term[portnum], B9600); cfsetospeed(&term[portnum], B9600); if(tcsetattr(fd[portnum], TCSANOW, &term[portnum]) < 0 ) { OWERROR(OWERROR_SYSTEM_RESOURCE_INIT_FAILED); perror("owTouchReset: Error with tcsetattr 1"); close(fd[portnum]); return FALSE; } /* Send the reset pulse */ wbuff = 0xF0; write(fd[portnum], &wbuff, 1); /* Set timeout */ timeout_tv.tv_usec = 0; timeout_tv.tv_sec = TIMEOUT; /* Clear set */ FD_ZERO(&readset); /* Add filedescriptor to set */ FD_SET(fd[portnum], &readset); /* Read byte if it doesn't timeout first */ if (select(fd[portnum]+1, &readset, NULL, NULL, &timeout_tv) > 0 ) { /* Is there something to read? */ if (FD_ISSET(fd[portnum], &readset)) { /* Read in the result */ read(fd[portnum], &result, 1); if (result == 0) /* Data line is a short to ground */ stat = FALSE; if (result != 0xF0) { /* Got a response */ /* Here we should check for alarms and errors */ stat = TRUE; } else { /* No device responding */ OWERROR(OWERROR_NO_DEVICES_ON_NET); stat = FALSE; } } } else { /* Timed out*/ stat = FALSE; } /* Set input and output speed to 115.2k */ cfsetispeed(&term[portnum], B115200); cfsetospeed(&term[portnum], B115200); /* set to 6 data bits */ term[portnum].c_cflag |= CS6; if (tcsetattr(fd[portnum], TCSANOW, &term[portnum] ) < 0 ) { OWERROR(OWERROR_SYSTEM_RESOURCE_INIT_FAILED); perror("Reset: Error with tcsetattr 2"); close(fd[portnum]); return FALSE; } return stat; } void owTouchBlock( int portnum, int timeout, int nbits, uchar *transfer_buf) { fd_set readset; char *buf; struct timeval timeout_tv; unsigned char inch = 0; unsigned int i; unsigned int bit_counter = 0; unsigned int nretrieved_bits; unsigned int nread_bits; int nbits2; if (nbits == 0) return; /* Allocate 'nbits' number of bytes for buf */ /* alloca() should be faster then malloc but ... */ buf = alloca(nbits); if (buf == NULL) { fprintf(stderr, "owTouchBlock: Could not allocate %d bytes of memory.\n", nbits); return; } /* Flush the input and output buffers */ tcflush(fd[portnum], TCIOFLUSH); /* Construct string of bytes representing bits to be sent */ for (i = 0; i < nbits; i++) buf[i] = (transfer_buf[i/8] & (1 << (i & 0x7))) ? 0xFF : 0x00; /* send and receive blocks of UART_FIFO_SIZE or less */ while (nbits != 0) { /* Make sure we don't send buffers bigger then UART_FIFO_SIZE */ nbits2 = (nbits < UART_FIFO_SIZE) ? nbits : UART_FIFO_SIZE; nbits -= nbits2; /* write nbits2 bits of buffer to network */ write(fd[portnum], buf, nbits2); /* read N bytes (bits) paired with above write */ nretrieved_bits = 0; while (nretrieved_bits < nbits2) { /* Initialize readset */ FD_ZERO(&readset); FD_SET(fd[portnum], &readset); /* Initialize timeout */ timeout_tv.tv_usec = 0; timeout_tv.tv_sec = timeout; /* Read bytes if it doesn't timeout first */ if (select(fd[portnum]+1, &readset, NULL, NULL, &timeout_tv) > 0) { /* Is there something to read? */ if (FD_ISSET(fd[portnum], &readset)) { /* read it into buf */ nread_bits = read(fd[portnum], buf, nbits2 - nretrieved_bits); /* loop over the buffer and extract the least significant bits * and put it in inch */ for (i = 0; i < nread_bits; i++) { inch >>= 1; /* mask bit 1 of buf, if bit is a '1' set bit 8 of inch, * if bit is a '0' leave bit 8 of inch unset */ inch |= (buf[i] & 0x01) ? 0x80 : 0x00; nretrieved_bits++; bit_counter++; if ((bit_counter % 8) == 0) { /* we have a full byte */ *transfer_buf = inch; transfer_buf++; inch = 0; } } } else { /* Wicked?, some signal or something */ printf("b0rked\n"); return; } } else { /* Timed out */ return; } } buf += nbits2; } if ((bit_counter % 8) != 0) /* this is not a full byte */ *transfer_buf = inch; } int owTouchBits( int portnum, int timeout, int nbits, SMALLINT outch ) { uchar r = outch; owTouchBlock(portnum, timeout, nbits, &r); return r; } //-------------------------------------------------------------------------- // Send 1 bit of communication to the 1-Wire Net and return the // result 1 bit read from the 1-Wire Net. The parameter 'sendbit' // least significant bit is used and the least significant bit // of the result is the return bit. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'sendbit' - the least significant bit is the bit to send // // Returns: 0: 0 bit read from sendbit // 1: 1 bit read from sendbit // SMALLINT owTouchBit(int portnum, SMALLINT sbit) { //unsigned char c = 0; unsigned char sendbit; unsigned char inbit = 0; fd_set readset; struct timeval tv; /* Flush the input and output buffers */ tcflush( fd[portnum], TCIOFLUSH ); /* Get the bit ready to be sent */ sendbit = (sbit & 0x01) ? 0xFF : 0x00; /* Send the bits/get the bits */ write( fd[portnum], &sendbit, 1 ); /* Send the bit */ /* Get the incoming bit if there is one */ /* Initialize readset */ FD_ZERO(&readset); FD_SET(fd[portnum], &readset); /* Set timeout*/ tv.tv_usec = 0; tv.tv_sec = 5; /* Read byte if it doesn't timeout first */ if( select( fd[portnum]+1, &readset, NULL, NULL, &tv ) > 0 ) { /* Is there something to read? */ if( FD_ISSET( fd[portnum], &readset ) ) { read(fd[portnum], &inbit, 1); inbit &= 0x01; } else { /* Wicked?, some signal or something */ printf("b0rked\n"); } } else { return 0xFF; } //printf("TouchBit: sendbit: %02X, inbit: %02X\n", sendbit, inbit); return inbit; } /* Send 8 bits of communication to the 1-Wire Net and return the * result 8 bits read from the 1-Wire Net. The parameter 'sendbyte' * least significant 8 bits are used and the least significant 8 bits * of the result is the return byte. */ SMALLINT owTouchByte(int portnum, SMALLINT sendbyte) { return owTouchBits(portnum, TIMEOUT, 8, sendbyte); } /* Send 8 bits of communication to the 1-Wire Net and verify that the * 8 bits read from the 1-Wire Net is the same (write operation). * The parameter 'sendbyte' least significant 8 bits are used. * Returns TRUE on sucess and FALSE if operation failed */ SMALLINT owWriteByte(int portnum, SMALLINT sendbyte) { return (owTouchByte(portnum,sendbyte) == sendbyte) ? TRUE : FALSE; } /* Send 8 bits of read communication to the 1-Wire Net and and return the * result 8 bits read from the 1-Wire Net. */ SMALLINT owReadByte(int portnum) { return owTouchByte(portnum,0xFF); } /* Set the 1-Wire net communication speed. * The passive adapter only supports normal speed. Returns MODE_NORMAL wich * means that current speed is normal */ SMALLINT owSpeed(int portnum, SMALLINT new_speed) { return MODE_NORMAL; } /* The passive adapter has only one line level, and that level depends on the * serial port. */ SMALLINT owLevel(int portnum, SMALLINT new_level) { return new_level; } /* No support for eeprom programming on the passive adapter */ SMALLINT owProgramPulse(int portnum) { return FALSE; } /* 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); } /* 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 clock() / 1000;; } //-------------------------------------------------------------------------- // Send 8 bits of communication to the 1-Wire Net and verify that the // 8 bits read from the 1-Wire Net is the same (write operation). // The parameter 'sendbyte' least significant 8 bits are used. After the // 8 bits are sent change the level of the 1-Wire net. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'sendbyte' - 8 bits to send (least significant byte) // // Returns: TRUE: bytes written and echo was the same // FALSE: echo was not the same // SMALLINT owWriteBytePower(int portnum, SMALLINT sendbyte) { // replace if platform has better implementation (faster response) if (!hasPowerDelivery(portnum)) return FALSE; if(owTouchByte(portnum,sendbyte) != sendbyte) return FALSE; if(owLevel(portnum,MODE_STRONG5) != MODE_STRONG5) return FALSE; return TRUE; } //-------------------------------------------------------------------------- // Send 1 bit of communication to the 1-Wire Net and verify that the // response matches the 'applyPowerResponse' bit and apply power delivery // to the 1-Wire net. Note that some implementations may apply the power // first and then turn it off if the response is incorrect. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'applyPowerResponse' - 1 bit response to check, if correct then start // power delivery // // Returns: TRUE: bit written and response correct, strong pullup now on // FALSE: response incorrect // SMALLINT owReadBitPower(int portnum, SMALLINT applyPowerResponse) { // replace if platform has better implementation (faster response) if (!hasPowerDelivery(portnum)) return FALSE; if(owTouchBit(portnum, 0x01) != applyPowerResponse) return FALSE; if(owLevel(portnum, MODE_STRONG5) != MODE_STRONG5) return FALSE; return TRUE; } /* I'm not realy sure about this but it works for digitemp. If it * means the adapter has a separate power line this should be false. */ SMALLINT hasPowerDelivery(int portnum) { return TRUE; } /* Passive adapter dosen't suport OverDrive due to limitations in * the way data is transfered. */ SMALLINT hasOverDrive(int portnum) { return FALSE; } /* Passive adapter doesn't support eeprom programming */ SMALLINT hasProgramPulse(int portnum) { return FALSE; } digitemp-3.6.0+dfsg1/userial/ds9097/ownet.c0000644000175000017500000004532611055427176016753 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // ownet.C - Network functions for 1-Wire net devices. // // Version: 2.01 // // History: 1.00 -> 1.01 Change to owFamilySearchSetup, LastDiscrepancy[portnum] // was set to 64 instead of 8 to enable devices with // early contention to go in the '0' direction first. // 1.02 -> 1.03 Initialized goodbits in owVerify // 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for // multiple ports. // 2.00 -> 2.01 Added support for owError library // #include #include #include // exportable functions defined in ownet.c SMALLINT bitacc(SMALLINT,SMALLINT,SMALLINT,uchar *); // global variables for this module to hold search state information static SMALLINT LastDiscrepancy[MAX_PORTNUM]; static SMALLINT LastFamilyDiscrepancy[MAX_PORTNUM]; static SMALLINT LastDevice[MAX_PORTNUM]; uchar SerialNum[MAX_PORTNUM][8]; //-------------------------------------------------------------------------- // The 'owFirst' finds the first device on the 1-Wire Net This function // contains one parameter 'alarm_only'. When // 'alarm_only' 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. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'do_reset' - TRUE (1) perform reset before search, FALSE (0) do not // perform reset before search. // 'alarm_only' - 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[portnum] // FALSE (0): There are no devices on the 1-Wire Net. // SMALLINT owFirst(int portnum, SMALLINT do_reset, SMALLINT alarm_only) { // reset the search state LastDiscrepancy[portnum] = 0; LastDevice[portnum] = FALSE; LastFamilyDiscrepancy[portnum] = 0; return owNext(portnum,do_reset,alarm_only); } //-------------------------------------------------------------------------- // The 'owNext' function does a general search. This function // continues from the previos search state. The search state // can be reset by using the 'owFirst' function. // This function contains one parameter 'alarm_only'. // When 'alarm_only' 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. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'do_reset' - TRUE (1) perform reset before search, FALSE (0) do not // perform reset before search. // 'alarm_only' - 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[portnum] // FALSE (0): when no new device was found. Either the // last search was the last device or there // are no devices on the 1-Wire Net. // SMALLINT owNext(int portnum, SMALLINT do_reset, SMALLINT alarm_only) { uchar bit_test, search_direction, bit_number; uchar last_zero, serial_byte_number, next_result; uchar serial_byte_mask; uchar lastcrc8=0; // initialize for search bit_number = 1; last_zero = 0; serial_byte_number = 0; serial_byte_mask = 1; next_result = 0; setcrc8(portnum,0); // if the last call was not the last one if (!LastDevice[portnum]) { // check if reset first is requested if (do_reset) { // reset the 1-wire // if there are no parts on 1-wire, return FALSE if (!owTouchReset(portnum)) { // printf("owTouchReset failed\r\n"); // reset the search LastDiscrepancy[portnum] = 0; LastFamilyDiscrepancy[portnum] = 0; OWERROR(OWERROR_NO_DEVICES_ON_NET); return FALSE; } } // If finding alarming devices issue a different command if (alarm_only) owWriteByte(portnum,0xEC); // issue the alarming search command else owWriteByte(portnum,0xF0); // issue the search command //pause before beginning the search //usDelay(100); // loop to do the search do { // read a bit and its compliment bit_test = owTouchBit(portnum,1) << 1; bit_test |= owTouchBit(portnum,1); // check for no devices on 1-wire if (bit_test == 3) break; else { // all devices coupled have 0 or 1 if (bit_test > 0) search_direction = !(bit_test & 0x01); // bit write value for search else { // if this discrepancy if before the Last Discrepancy // on a previous next then pick the same as last time if (bit_number < LastDiscrepancy[portnum]) search_direction = ((SerialNum[portnum][serial_byte_number] & serial_byte_mask) > 0); else // if equal to last pick 1, if not then pick 0 search_direction = (bit_number == LastDiscrepancy[portnum]); // if 0 was picked then record its position in LastZero if (search_direction == 0) last_zero = bit_number; // check for Last discrepancy in family if (last_zero < 9) LastFamilyDiscrepancy[portnum] = last_zero; } // set or clear the bit in the SerialNum[portnum] byte serial_byte_number // with mask serial_byte_mask if (search_direction == 1) SerialNum[portnum][serial_byte_number] |= serial_byte_mask; else SerialNum[portnum][serial_byte_number] &= ~serial_byte_mask; // serial number search direction write bit owTouchBit(portnum,search_direction); // increment the byte counter bit_number // and shift the mask serial_byte_mask bit_number++; serial_byte_mask <<= 1; // if the mask is 0 then go to new SerialNum[portnum] byte serial_byte_number // and reset mask if (serial_byte_mask == 0) { lastcrc8 = docrc8(portnum,SerialNum[portnum][serial_byte_number]); // accumulate the CRC serial_byte_number++; serial_byte_mask = 1; } } } while(serial_byte_number < 8); // loop until through all SerialNum[portnum] bytes 0-7 // if the search was successful then if (!((bit_number < 65) || lastcrc8)) { // search successful so set LastDiscrepancy[portnum],LastDevice[portnum],next_result LastDiscrepancy[portnum] = last_zero; LastDevice[portnum] = (LastDiscrepancy[portnum] == 0); next_result = TRUE; } } // if no device found then reset counters so next 'next' will be // like a first if (!next_result || !SerialNum[portnum][0]) { LastDiscrepancy[portnum] = 0; LastDevice[portnum] = FALSE; LastFamilyDiscrepancy[portnum] = 0; next_result = FALSE; } return next_result; } //-------------------------------------------------------------------------- // The 'owSerialNum' function either reads or sets the SerialNum buffer // that is used in the search functions 'owFirst' and 'owNext'. // This function contains two parameters, 'serialnum_buf' is a pointer // to a buffer provided by the caller. 'serialnum_buf' should point to // an array of 8 unsigned chars. The second parameter is a flag called // 'do_read' 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. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'serialnum_buf' - buffer to that contains the serial number to set // when do_read = FALSE (0) and buffer to get the serial // number when do_read = TRUE (1). // 'do_read' - flag to indicate reading (1) or setting (0) the current // serial number. // void owSerialNum(int portnum, uchar *serialnum_buf, SMALLINT do_read) { uchar i; // read the internal buffer and place in 'serialnum_buf' if (do_read) { for (i = 0; i < 8; i++) serialnum_buf[i] = SerialNum[portnum][i]; } // set the internal buffer from the data in 'serialnum_buf' else { for (i = 0; i < 8; i++) SerialNum[portnum][i] = serialnum_buf[i]; } } //-------------------------------------------------------------------------- // Setup the search algorithm to find a certain family of devices // the next time a search function is called 'owNext'. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'search_family' - family code type to set the search algorithm to find // next. // void owFamilySearchSetup(int portnum, SMALLINT search_family) { uchar i; // set the search state to find SearchFamily type devices SerialNum[portnum][0] = search_family; for (i = 1; i < 8; i++) SerialNum[portnum][i] = 0; LastDiscrepancy[portnum] = 64; LastDevice[portnum] = FALSE; } //-------------------------------------------------------------------------- // Set the current search state to skip the current family code. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // void owSkipFamily(int portnum) { // set the Last discrepancy to last family discrepancy LastDiscrepancy[portnum] = LastFamilyDiscrepancy[portnum]; // check for end of list if (LastDiscrepancy[portnum] == 0) LastDevice[portnum] = TRUE; } //-------------------------------------------------------------------------- // The 'owAccess' 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. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // // 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. // SMALLINT owAccess(int portnum) { uchar sendpacket[9]; uchar i; // reset the 1-wire if (owTouchReset(portnum)) { // create a buffer to use with block function // match Serial Number command 0x55 sendpacket[0] = 0x55; // Serial Number for (i = 1; i < 9; i++) sendpacket[i] = SerialNum[portnum][i-1]; // send/recieve the transfer buffer if (owBlock(portnum,FALSE,sendpacket,9)) { // verify that the echo of the writes was correct for (i = 1; i < 9; i++) if (sendpacket[i] != SerialNum[portnum][i-1]) return FALSE; if (sendpacket[0] != 0x55) { OWERROR(OWERROR_WRITE_VERIFY_FAILED); return FALSE; } else return TRUE; } else OWERROR(OWERROR_BLOCK_FAILED); } else OWERROR(OWERROR_NO_DEVICES_ON_NET); // reset or match echo failed return FALSE; } //---------------------------------------------------------------------- // The function 'owVerify' verifies that the current device // is in contact with the 1-Wire Net. // Using the find alarm command 0xEC will verify that the device // is in contact with the 1-Wire Net and is in an 'alarm' state. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'alarm_only' - 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 1-Wire Net // with alarm_only == FALSE // or verified to be on the 1-Wire Net // AND in an alarm state when // alarm_only == TRUE. // FALSE (0): the 1-Wire device was not on the // 1-Wire Net or if alarm_only // == TRUE, the device may be on the // 1-Wire Net but in a non-alarm state. // SMALLINT owVerify(int portnum, SMALLINT alarm_only) { uchar i,sendlen=0,goodbits=0,cnt=0,s,tst; uchar sendpacket[50]; // construct the search if (alarm_only) sendpacket[sendlen++] = 0xEC; // issue the alarming search command else sendpacket[sendlen++] = 0xF0; // issue the search command // set all bits at first for (i = 1; i <= 24; i++) sendpacket[sendlen++] = 0xFF; // now set or clear apropriate bits for search for (i = 0; i < 64; i++) bitacc(WRITE_FUNCTION,bitacc(READ_FUNCTION,0,i,&SerialNum[portnum][0]),(int)((i+1)*3-1),&sendpacket[1]); // send/recieve the transfer buffer if (owBlock(portnum,TRUE,sendpacket,sendlen)) { // check results to see if it was a success for (i = 0; i < 192; i += 3) { tst = (bitacc(READ_FUNCTION,0,i,&sendpacket[1]) << 1) | bitacc(READ_FUNCTION,0,(int)(i+1),&sendpacket[1]); s = bitacc(READ_FUNCTION,0,cnt++,&SerialNum[portnum][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; } else OWERROR(OWERROR_BLOCK_FAILED); // 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. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // // Returns: TRUE: If the device is present on the 1-Wire Net 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. // SMALLINT owOverdriveAccess(int portnum) { uchar sendpacket[8]; uchar i, bad_echo = FALSE; // make sure normal level owLevel(portnum,MODE_NORMAL); // force to normal communication speed owSpeed(portnum,MODE_NORMAL); // call the 1-Wire Net reset function if (owTouchReset(portnum)) { // send the match command 0x69 if (owWriteByte(portnum,0x69)) { // switch to overdrive communication speed owSpeed(portnum,MODE_OVERDRIVE); // create a buffer to use with block function // Serial Number for (i = 0; i < 8; i++) sendpacket[i] = SerialNum[portnum][i]; // send/recieve the transfer buffer if (owBlock(portnum,FALSE,sendpacket,8)) { // verify that the echo of the writes was correct for (i = 0; i < 8; i++) if (sendpacket[i] != SerialNum[portnum][i]) bad_echo = TRUE; // if echo ok then success if (!bad_echo) return TRUE; else OWERROR(OWERROR_WRITE_VERIFY_FAILED); } else OWERROR(OWERROR_BLOCK_FAILED); } else OWERROR(OWERROR_WRITE_BYTE_FAILED); } else OWERROR(OWERROR_NO_DEVICES_ON_NET); // failure, force back to normal communication speed owSpeed(portnum,MODE_NORMAL); return FALSE; } //-------------------------------------------------------------------------- // 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 // SMALLINT bitacc(SMALLINT op, SMALLINT state, SMALLINT loc, uchar *buf) { SMALLINT 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); } digitemp-3.6.0+dfsg1/userial/ds9097/owerr.c0000644000175000017500000003066610632073746016756 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // owerr.c - Library functions for error handling with 1-Wire library // // Version: 1.00 // #include #ifndef _WIN32_WCE #include #endif #include "ownet.h" #ifndef SIZE_OWERROR_STACK #ifdef SMALL_MEMORY_TARGET //for small memory, only hole 1 error #define SIZE_OWERROR_STACK 1 #else #define SIZE_OWERROR_STACK 10 #endif #endif //--------------------------------------------------------------------------- // Variables //--------------------------------------------------------------------------- // Error Struct for holding error information. // In DEBUG, this will also hold the line number and filename. typedef struct { int owErrorNum; #ifdef DEBUG int lineno; char *filename; #endif } owErrorStruct; // Ring-buffer used for stack. // In case of overflow, deepest error is over-written. static owErrorStruct owErrorStack[SIZE_OWERROR_STACK]; // Stack pointer to top-most error. static int owErrorPointer = 0; //--------------------------------------------------------------------------- // Functions Definitions //--------------------------------------------------------------------------- int owGetErrorNum(void); void owClearError(void); int owHasErrors(void); #ifdef DEBUG void owRaiseError(int,int,char*); #else void owRaiseError(int); #endif #ifndef SMALL_MEMORY_TARGET void owPrintErrorMsg(FILE *); void owPrintErrorMsgStd(); char *owGetErrorMsg(int); #endif //-------------------------------------------------------------------------- // The 'owGetErroNum' returns the error code of the top-most error on the // error stack. NOTE: This function has the side effect of popping the // current error off the stack. All successive calls to 'owGetErrorNum' // will further clear the error stack. // // For list of error codes, see 'ownet.h' // // Returns: int : The error code of the top-most error on the stack // int owGetErrorNum(void) { int i = owErrorStack[ owErrorPointer ].owErrorNum; owErrorStack[ owErrorPointer ].owErrorNum = 0; if(!owErrorPointer) owErrorPointer = SIZE_OWERROR_STACK - 1; else owErrorPointer = (owErrorPointer - 1); return i; } //-------------------------------------------------------------------------- // The 'owClearError' clears all the errors. // void owClearError(void) { owErrorStack[ owErrorPointer ].owErrorNum = 0; } //-------------------------------------------------------------------------- // The 'owHasErrors' is a boolean test function which tests whether or not // a valid error is waiting on the stack. // // Returns: TRUE (1) : When there are errors on the stack. // FALSE (0): When stack's errors are set to 0, or NO_ERROR_SET. // int owHasErrors(void) { if(owErrorStack[ owErrorPointer ].owErrorNum) return 1; //TRUE else return 0; //FALSE } #ifdef DEBUG //-------------------------------------------------------------------------- // The 'owRaiseError' is the method for raising an error onto the error // stack. // // Arguments: int err - the error code you wish to raise. // int lineno - DEBUG only - the line number where it was raised // char* filename - DEBUG only - the file name where it occured. // void owRaiseError(int err, int lineno, char* filename) { owErrorPointer = (owErrorPointer + 1) % SIZE_OWERROR_STACK; owErrorStack[ owErrorPointer ].owErrorNum = err; owErrorStack[ owErrorPointer ].lineno = lineno; owErrorStack[ owErrorPointer ].filename = filename; } #else //-------------------------------------------------------------------------- // The 'owRaiseError' is the method for raising an error onto the error // stack. // // Arguments: int err - the error code you wish to raise. // void owRaiseError(int err) { owErrorPointer = (owErrorPointer + 1) % SIZE_OWERROR_STACK; owErrorStack[ owErrorPointer ].owErrorNum = err; } #endif // SMALL_MEMORY_TARGET - embedded microcontrollers, where these // messaging functions might not make any sense. #ifndef SMALL_MEMORY_TARGET //Array of meaningful error messages to associate with codes. //Not used on targets with low memory (i.e. PIC). static char *owErrorMsg[103] = { /*000*/ "No Error Was Set", /*001*/ "No Devices found on 1-Wire Network", /*002*/ "1-Wire Net Reset Failed", /*003*/ "Search ROM Error: Couldn't locate next device on 1-Wire", /*004*/ "Access Failed: Could not select device", /*005*/ "DS2480B Adapter Not Detected", /*006*/ "DS2480B: Wrong Baud", /*007*/ "DS2480B: Bad Response", /*008*/ "Open COM Failed", /*009*/ "Write COM Failed", /*010*/ "Read COM Failed", /*011*/ "Data Block Too Large", /*012*/ "Block Transfer failed", /*013*/ "Program Pulse Failed", /*014*/ "Program Byte Failed", /*015*/ "Write Byte Failed", /*016*/ "Read Byte Failed", /*017*/ "Write Verify Failed", /*018*/ "Read Verify Failed", /*019*/ "Write Scratchpad Failed", /*020*/ "Copy Scratchpad Failed", /*021*/ "Incorrect CRC Length", /*022*/ "CRC Failed", /*023*/ "Failed to acquire a necessary system resource", /*024*/ "Failed to initialize system resource", /*025*/ "Data too long to fit on specified device.", /*026*/ "Read exceeds memory bank end.", /*027*/ "Write exceeds memory bank end.", /*028*/ "Device select failed", /*029*/ "Read Scratch Pad verify failed.", /*030*/ "Copy scratchpad complete not found", /*031*/ "Erase scratchpad complete not found", /*032*/ "Address read back from scrachpad was incorrect", /*033*/ "Read page with extra-info not supported by this memory bank", /*034*/ "Read page packet with extra-info not supported by this memory bank", /*035*/ "Length of packet requested exceeds page size", /*036*/ "Invalid length in packet", /*037*/ "Program pulse required but not available", /*038*/ "Trying to access a read-only memory bank", /*039*/ "Current bank is not general purpose memory", /*040*/ "Read back from write compare is incorrect, page may be locked", /*041*/ "Invalid page number for this memory bank", /*042*/ "Read page with CRC not supported by this memory bank", /*043*/ "Read page with CRC and extra-info not supported by this memory bank", /*044*/ "Read back from write incorrect, could not lock page", /*045*/ "Read back from write incorrect, could not lock redirect byte", /*046*/ "The read of the status was not completed.", /*047*/ "Page redirection not supported by this memory bank", /*048*/ "Lock Page redirection not supported by this memory bank", /*049*/ "Read back byte on EPROM programming did not match.", /*050*/ "Can not write to a page that is locked.", /*051*/ "Can not lock a redirected page that has already been locked.", /*052*/ "Trying to redirect a locked redirected page.", /*053*/ "Trying to lock a page that is already locked.", /*054*/ "Trying to write to a memory bank that is write protected.", /*055*/ "Error due to not matching MAC.", /*056*/ "Memory Bank is write protected.", /*057*/ "Secret is write protected, can not Load First Secret.", /*058*/ "Error in Reading Scratchpad after Computing Next Secret.", /*059*/ "Load Error from Loading First Secret.", /*060*/ "Power delivery required but not available", /*061*/ "Not a valid file name.", /*062*/ "Unable to Create a Directory in this part.", /*063*/ "That file already exists.", /*064*/ "The directory is not empty.", /*065*/ "The wrong type of part for this operation.", /*066*/ "The max len for this file is too small.", /*067*/ "This is not a write once bank.", /*068*/ "The file can not be found.", /*069*/ "There is not enough space availabe.", /*070*/ "There is not a page to match that bit in the bitmap.", /*071*/ "There are no jobs for EPROM parts.", /*072*/ "Function not supported to modify attributes.", /*073*/ "Handle is not in use.", /*074*/ "Tring to read a write only file.", /*075*/ "There is no handle available for use.", /*076*/ "The directory provided is an invalid directory.", /*077*/ "Handle does not exist.", /*078*/ "Serial Number did not match with current job.", /*079*/ "Can not program EPROM because a non-EPROM part on the network.", /*080*/ "Write protect redirection byte is set.", /*081*/ "There is an inappropriate directory length.", /*082*/ "The file has already been terminated.", /*083*/ "Failed to read memory page of iButton part.", /*084*/ "Failed to match scratchpad of iButton part.", /*085*/ "Failed to erase scratchpad of iButton part.", /*086*/ "Failed to read scratchpad of iButton part.", /*087*/ "Failed to execute SHA function on SHA iButton.", /*088*/ "SHA iButton did not return a status completion byte.", /*089*/ "Write data page failed.", /*090*/ "Copy secret into secret memory pages failed.", /*091*/ "Bind unique secret to iButton failed.", /*092*/ "Could not install secret into user token.", /*093*/ "Transaction Incomplete: signature did not match.", /*094*/ "Transaction Incomplete: could not sign service data.", /*095*/ "User token did not provide a valid authentication response.", /*096*/ "Failed to answer a challenge on the user token.", /*097*/ "Failed to create a challenge on the coprocessor.", /*098*/ "Transaction Incomplete: service data was not valid.", /*099*/ "Transaction Incomplete: service data was not updated.", /*100*/ "Unrecoverable, catastrophic service failure occured.", /*101*/ "Load First Secret from scratchpad data failed.", /*102*/ "Failed to match signature of user's service data." }; char *owGetErrorMsg(int err) { return owErrorMsg[err]; } //-------------------------------------------------------------------------- // The 'owPrintErrorMsg' is the method for printing an error from the stack. // The destination for the print is specified by the argument, fileno, which // can be stderr, stdout, or a log file. In non-debug mode, the output is // of the form: // Error num: Error msg // // In debug-mode, the output is of the form: // Error num: filename line#: Error msg // // NOTE: This function has the side-effect of popping the error off the stack. // // Arguments: FILE*: the destination for printing. // void owPrintErrorMsg(FILE *fileno) { #ifdef DEBUG int l = owErrorStack[ owErrorPointer ].lineno; char *f = owErrorStack[ owErrorPointer ].filename; int err = owGetErrorNum(); fprintf(fileno,"Error %d: %s line %d: %s\r\n",err,f,l,owErrorMsg[err]); #else int err = owGetErrorNum(); fprintf(fileno,"Error %d: %s\r\n",err,owErrorMsg[err]); #endif } // Same as above, except uses default printf output void owPrintErrorMsgStd() { #ifdef DEBUG int l = owErrorStack[ owErrorPointer ].lineno; char *f = owErrorStack[ owErrorPointer ].filename; int err = owGetErrorNum(); printf("Error %d: %s line %d: %s\r\n",err,f,l,owErrorMsg[err]); #else int err = owGetErrorNum(); printf("Error %d: %s\r\n",err,owErrorMsg[err]); #endif } #endif digitemp-3.6.0+dfsg1/userial/ds9097/owtran.c0000644000175000017500000001461310632073746017124 0ustar ryanryan//--------------------------------------------------------------------------- // 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. //--------------------------------------------------------------------------- // // owTran.C - Transport functions for 1-Wire devices. // // Version: 2.01 // // History: 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for // multiple ports. // 2.00 -> 2.01 Added support for owError library // #include #include //-------------------------------------------------------------------------- // The 'owBlock' transfers a block of data to and from the // 1-Wire Net with an optional reset at the begining of communication. // The result is returned in the same buffer. // // 'do_reset' - cause a owTouchReset to occure at the begining of // communication TRUE(1) or not FALSE(0) // 'tran_buf' - pointer to a block of unsigned // chars of length 'TranferLength' that will be sent // to the 1-Wire Net // 'tran_len' - length in bytes to transfer // Supported devices: all // // Returns: TRUE (1) : The optional reset returned a valid // presence (do_reset == TRUE) or there // was no reset required. // FALSE (0): The reset did not return a valid prsence // (do_reset == TRUE). // // The maximum tran_len is 160 // SMALLINT owBlock(int portnum, SMALLINT do_reset, uchar *tran_buf, SMALLINT tran_len) { uchar i; // check for a block too big if (tran_len > 160) { OWERROR(OWERROR_BLOCK_TOO_BIG); return FALSE; } // check if need to do a owTouchReset first if (do_reset) { if (!owTouchReset(portnum)) { OWERROR(OWERROR_NO_DEVICES_ON_NET); return FALSE; } } // send and receive the buffer for (i = 0; i < tran_len; i++) tran_buf[i] = (uchar)owTouchByte(portnum,tran_buf[i]); return TRUE; } //-------------------------------------------------------------------------- // Write a byte to an EPROM 1-Wire device. // // Supported devices: crc_type=0(CRC8) // DS1982 // crc_type=1(CRC16) // DS1985, DS1986, DS2407 // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'write_byte' - byte to program // 'addr' - address of byte to program // 'write_cmd' - command used to write (0x0F reg mem, 0x55 status) // 'crc_type' - CRC used (0 CRC8, 1 CRC16) // 'do_access' - Flag to access device for each byte // (0 skip access, 1 do the access) // WARNING, only use do_access=0 if programing the NEXT // byte immediatly after the previous byte. // // Returns: >=0 success, this is the resulting byte from the program // effort // -1 error, device not connected or program pulse voltage // not available // SMALLINT owProgramByte(int portnum, SMALLINT write_byte, int addr, SMALLINT write_cmd, SMALLINT crc_type, SMALLINT do_access) { ushort lastcrc16; uchar lastcrc8; // optionally access the device if (do_access) { if (!owAccess(portnum)) { OWERROR(OWERROR_ACCESS_FAILED); return -1; } // send the write command if (!owWriteByte(portnum,write_cmd)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return -1; } // send the address if (!owWriteByte(portnum,addr & 0xFF) || !owWriteByte(portnum,addr >> 8)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return -1; } } // send the data to write if (!owWriteByte(portnum,write_byte)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return -1; } // read the CRC if (crc_type == 0) { // calculate CRC8 if (do_access) { setcrc8(portnum,0); docrc8(portnum,(uchar)write_cmd); docrc8(portnum,(uchar)(addr & 0xFF)); docrc8(portnum,(uchar)(addr >> 8)); } else setcrc8(portnum,(uchar)(addr & 0xFF)); docrc8(portnum,(uchar)write_byte); // read and calculate the read crc lastcrc8 = docrc8(portnum,(uchar)owReadByte(portnum)); // crc should now be 0x00 if (lastcrc8 != 0) { OWERROR(OWERROR_CRC_FAILED); return -1; } } else { // CRC16 if (do_access) { setcrc16(portnum,0); docrc16(portnum,(ushort)write_cmd); docrc16(portnum,(ushort)(addr & 0xFF)); docrc16(portnum,(ushort)(addr >> 8)); } else setcrc16(portnum,(ushort)addr); docrc16(portnum,(ushort)write_byte); // read and calculate the read crc docrc16(portnum,(ushort)owReadByte(portnum)); lastcrc16 = docrc16(portnum,(ushort)owReadByte(portnum)); // crc should now be 0xB001 if (lastcrc16 != 0xB001) return -1; } // send the program pulse if (!owProgramPulse(portnum)) { OWERROR(OWERROR_PROGRAM_PULSE_FAILED); return -1; } // read back and return the resulting byte return owReadByte(portnum); } digitemp-3.6.0+dfsg1/userial/owproto.h0000644000175000017500000000417311055427321016361 0ustar ryanryan/* Prototypes for userial driver functions */ /* From other low level userial files */ SMALLINT owAccess(int); #ifndef OWUSB SMALLINT owAcquire(int,char *); #else SMALLINT owAcquire(int,char *, char *); #endif /* OWUSB */ void owSerialNum(int,uchar *,SMALLINT); SMALLINT owWriteBytePower(int,SMALLINT); SMALLINT owWriteByte(int,SMALLINT); SMALLINT owReadByte(int); SMALLINT owLevel(int,SMALLINT); void msDelay(int); SMALLINT owBlock(int,SMALLINT,uchar *,SMALLINT); SMALLINT owTouchReset(int); #ifndef OWUSB void owRelease(int); #else void owRelease(int, char *); #endif /* OWUSB */ SMALLINT owFirst(int,SMALLINT,SMALLINT); SMALLINT owNext(int,SMALLINT,SMALLINT); /* From owerr.c */ int owGetErrorNum(void); void owClearError(void); int owHasErrors(void); #ifdef DEBUG void owRaiseError(int,int,char*); #else void owRaiseError(int); #endif #ifndef SMALL_MEMORY_TARGET void owPrintErrorMsg(FILE *); void owPrintErrorMsgStd(); char *owGetErrorMsg(int); #endif /* From ioutil.c */ int EnterString(char *, char *, int, int); int EnterNum(char *, int, long *, long, long); int EnterHex(char *, int, ulong *); int ToHex(char ch); int getkeystroke(void); int key_abort(void); void ExitProg(char *, int); int getData(uchar*, int, SMALLINT); void PrintHex(uchar*, int); void PrintChars(uchar*, int); void PrintSerialNum(uchar*); /* From crcutil.c */ void setcrc16(int,ushort); ushort docrc16(int,ushort); void setcrc8(int,uchar); uchar docrc8(int,uchar); /* From swt1f.c */ int SetSwitch1F(int,uchar *,int,int,uchar *,int); int SwitchStateToString1F(int, char *); int FindBranchDevice(int,uchar *,uchar BranchSN[][8],int,int); int owBranchFirst(int,uchar *,int,int); int owBranchNext(int,uchar *,int,int); /* From cnt1d.c */ SMALLINT ReadCounter(int,int,ulong *); /* From ad26.c */ double Get_Temperature(int portnum); float Volt_Reading(int portnum, int vdd, int *cad); int PIO_Reading(int portnum, int pionum /* TS ignored so far */ ); /* From XXXlnk.c */ SMALLINT owTouchBit(int,SMALLINT); SMALLINT owSpeed(int,SMALLINT); SMALLINT owTouchByte(int portnum, SMALLINT sendbyte); SMALLINT owProgramPulse(int portnum); digitemp-3.6.0+dfsg1/userial/ioutil.c0000644000175000017500000002321510632073746016156 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // ioutil.c - I/O Utility functions // // Version: 2.00 // History: // #include #include #include #include #include #include "ownet.h" #ifdef __MC68K__ #include #include #endif // External functions extern int key_abort(void); // typedef typedef void Sigfunc(int); // local function prototypes int EnterString(char *, char *, int, int); int EnterNum(char *, int, long *, long, long); int EnterHex(char *, int, ulong *); int ToHex(char ch); int getkeystroke(void); int key_abort(void); void ExitProg(char *, int); int getData(uchar*, int, SMALLINT); void PrintHex(uchar*, int); void PrintChars(uchar*, int); void PrintSerialNum(uchar*); #ifndef __MC68K__ static void sig_ctrlc(int signo); #else int key_aborted = FALSE; #endif // global state of interrupt static int got_interrupt=0; //---------------------------------------------------------------------- // Enter a string // Leave the same if no characters entered // int EnterString(char *msg, char *buf, int min, int max) { int len,deflen; char ch,defbuf[80]; // check for abort if (key_abort()) return -1; // remember the start length deflen = strlen(buf); if (deflen < 80) sprintf(defbuf,buf); else defbuf[0] = 0; // prompt if (deflen < 30) printf("%s (%s): ",msg,buf); else printf("%s (%s):\n",msg,buf); // loop to get the file len = 0; for (;;) { // get a key ch = getkeystroke(); // check for abort if (key_abort()) return -1; // check the backspace key if (ch == 0x08) { if (len > 0) { // got a valid backspace len--; printf("\x008 \x008"); } } // escape key else if (ch == 0x1B) { printf("\n"); return -1; } // caraige return if (ch == 0x0A) { // check for special case (keep default) if ((len == 0) && (deflen > min)) { sprintf(buf,"%s",defbuf); printf("\n"); return deflen; } else if (len < min) continue; else { printf("\n"); return len; } } // valid key else if (len < max) { printf("%c",ch); // record the char buf[len++] = ch; } } } //---------------------------------------------------------------------- // Enter a decimal string and convert it to an unsigned long // Prompt again if not within min/max inclusive. // int EnterNum(char *msg, int numchars, long *value, long min, long max) { short tmp,cnt,isneg=FALSE; char ch; // check for abort if (key_abort()) return FALSE; // loop while not in correct range do { printf("%s (%ld): ",msg,*value); // loop for each character read cnt = 0; for (;;) { ch = getkeystroke(); // check for abort if (key_abort()) return FALSE; // negative flag if (ch == '-') { if (!isneg) { isneg = TRUE; printf("-"); cnt++; } } // backspace if (ch == 0x08) { if (cnt) { if (isneg && (cnt == 1)) isneg = FALSE; else *value /= 10; printf("%c %c",ch,ch); cnt--; } } // escape if (ch == 0x1B) { printf(" Aborted\n\n"); return FALSE; } // enter if (ch == 0x0A) { printf("\n"); break; } // number else if ((ch >= '0') && (ch <= '9')) { if (cnt == 0) *value = 0; if (cnt < numchars) { printf("%c",ch); tmp = ch - 0x30; *value *= 10; *value += tmp; cnt++; } } } if (isneg) *value = -*value; } while ((*value < min) || (*value > max)); return TRUE; } //---------------------------------------------------------------------- // Enter a hex string and convert it to an unsigned long // (1-8) characters // int EnterHex(char *msg, int numchars, ulong *value) { int tmp,cnt; int ch; // prompt printf("%s (enter hex, up to %d chars):",msg,numchars); *value = 0; cnt = 0; do { ch = getkeystroke(); if (ch == 0x08) { printf("%c %c",ch,ch); if (cnt) cnt--; } else if (ch == 0x1B) { printf(" Aborted\n\n"); return FALSE; } // caraige return else if (ch == 0x0A) { printf("\n"); return TRUE; } else { tmp = ToHex((char)ch); if (tmp) { printf("%c",ch); *value <<= 4; *value |= tmp; cnt++; } } } while (cnt < numchars); printf("\n"); return TRUE; } //------------------------------------------------------------------------ // Convert 1 hex character to binary. If not a hex character then // return 0. // int ToHex(char ch) { if ((ch >= '0') && (ch <= '9')) return ch - 0x30; else if ((ch >= 'A') && (ch <= 'F')) return ch - 0x37; else if ((ch >= 'a') && (ch <= 'f')) return ch - 0x57; else return 0; } //------------------------------------------------------------------------ // Get a character // int getkeystroke(void) { return fgetc(stdin); } //------------------------------------------------------------------------ // Check if key abort has occurred // int key_abort(void) { #ifdef __MC68K__ EventType event; EvtGetEvent(&event,1); if(event.eType == penDownEvent) key_aborted = TRUE; return key_aborted; #else static int didsetup=0; if (!didsetup) { if (signal(SIGINT,sig_ctrlc) == SIG_ERR) printf("could not setup ctrl-c handler\n"); didsetup = 1; } return got_interrupt; #endif } #ifndef __MC68K__ //------------------------------------------------------------------------ // Key abort interrupt handler // static void sig_ctrlc(int signo) { // set abort flag got_interrupt = 1; // print warning (may take awhile to abort) printf("<< CTRL-C key abort >>"); } #endif //------------------------------------------------------------------------ // Print message and exit program // void ExitProg(char *msg, int exit_code) { #ifndef __MC68K__ printf("%s\n",msg); exit(exit_code); #else // Add code to print exit criteria for Palm/Visor #endif } /** * Retrieve user input from the console in the form of hex or text. * * write_buff the buffer for the data to be written into. * * @return length of arra. */ int getData(uchar *write_buff, int max_len, SMALLINT gethex) { char ch; char hexchar[3]; int cnt = 0; int done = FALSE; if(!gethex) { do { ch = (char) getchar(); if(!isspace(ch) && cnt 0) done = TRUE; } while(!done); } else { hexchar[2] = 0; do { ch = (char) getchar(); if(!isspace(ch)) { hexchar[0] = ch; hexchar[1] = (char) getchar(); if(cnt 0)) done = TRUE; } while(!done); } return cnt; } void PrintHex(uchar* buffer, int cnt) { int i; for(i=0; i=0; i--) { printf("%02X", buffer[i]); } } digitemp-3.6.0+dfsg1/userial/thermo21.h0000644000175000017500000001100210632073746016306 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // thermo.h - Include file for Thermochron demo. // // Version: 2.00 // // History: // 1.03 -> 2.00 Reorganization of Public Domain Kit #ifndef THERMO_TYPES #define THERMO_TYPES // defines #define STATUS_PAGE 16 #define THERMO_FAM 0x21 #include // Typedefs #ifndef OW_UCHAR #define OW_UCHAR typedef unsigned char uchar; #ifdef WIN32 typedef unsigned short ushort; typedef unsigned long ulong; #endif #endif // structure to hold the mission status typedef struct { uchar serial_num[8]; // serial number of thermochron uchar mission_in_progress; // 1 mission in progres, 0 mission over uchar sample_rate; // minutes between samples uchar rollover_enable; // 1 if roll-over enabled uchar rollover_occurred; // 1 if roll-over occurred ushort start_delay; // minutes before mission starts ulong mission_start_time; // date/time when mission started ulong current_time; // current real-time clock value ulong download_time; // download stations time of reading ulong mission_samples; // number of samples in this mission ulong samples_total; // total number of samples taken by device uchar high_threshold; // raw temp of high threshold uchar low_threshold; // raw temp of low threshold // skip alarm modes and status for now uchar status_raw[32]; } MissionStatus; // structure to hold the histogram data typedef struct { ushort bin_count[56]; // counter per bin 0 to 55 float start_range[56]; // start temp range (C) in bin 0 to 55 float end_range[56]; // end temp range (C) in bin 0 to 55 uchar hist_raw[128]; // raw data for histogram } Histogram; // structure to hold the histogram data typedef struct { int num_low; // number of low events ulong low_start_time[12]; // start time of event 0 to 12 ulong low_end_time[12]; // end time of event 0 to 12 int num_high; // number of high events ulong high_start_time[12]; // start time of event 0 to 12 ulong high_end_time[12]; // end time of event 0 to 12 uchar alarm_raw[96]; // raw data for alarm events } TempAlarmEvents; // structure to hold the log data typedef struct { int num_log; // number of logs float temp[2048]; // temperature log in (C) ulong start_time; // start time of log int interval; // interval in seconds between logs uchar log_raw[2048]; // raw data for log } Log; // structure to hold all of the thermochron data state typedef struct { MissionStatus MissStat; // mission state Histogram HistData; // histogram data TempAlarmEvents AlarmData; // temperature alarm event data Log LogData; // log data } ThermoStateType; // type structure to holde time/date typedef struct { ushort second; ushort minute; ushort hour; ushort day; ushort month; ushort year; } timedate; #endif digitemp-3.6.0+dfsg1/userial/win32/0000755000175000017500000000000010632073746015444 5ustar ryanryandigitemp-3.6.0+dfsg1/userial/win32/win32lnk.c0000644000175000017500000003417410632073746017270 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // Win32Lnk.C - COM functions using Win32 to be used as a test // for DS2480 based Universal Serial Adapter 'U' // functions. // // Version: 2.01 // // History: 1.00 -> 1.01 Added function msDelay. // // 1.01 -> 1.02 Changed to generic OpenCOM/CloseCOM for easier // use with other platforms. // // 1.02 -> 1.03 Add function msGettick() // // 1.03 -> 2.00 Support for multiple ports. // 2.00 -> 2.01 Added error handling. Added circular-include check. // 2.01 -> 2.10 Added raw memory error handling and SMALLINT // 2.10 -> 3.00 Added memory bank functionality // Added file I/O operations // #include "ownet.h" #include "ds2480.h" #include #include // Win32 globals needed static HANDLE ComID[MAX_PORTNUM]; static OVERLAPPED osRead[MAX_PORTNUM],osWrite[MAX_PORTNUM]; static SMALLINT ComID_init = 0; //--------------------------------------------------------------------------- //-------- COM required functions for MLANU //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Attempt to open a com port. Keep the handle in ComID. // Set the starting baud rate to 9600. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number provided will // be used to indicate the port number desired when calling // all other functions in this library. // // // Returns: the port number if it was succesful otherwise -1 // int OpenCOMEx(char *port_zstr) { int portnum; if(!ComID_init) { int i; for(i=0; i=0 && !ComID[portnum], OWERROR_PORTNUM_ERROR, FALSE ); // open COMM device if ((ComID[portnum] = CreateFile( port_zstr, GENERIC_READ | GENERIC_WRITE, 0, NULL, // no security attrs OPEN_EXISTING, FILE_FLAG_OVERLAPPED, // overlapped I/O NULL )) == (HANDLE) -1 ) { ComID[portnum] = 0; OWERROR(OWERROR_GET_SYSTEM_RESOURCE_FAILED); return (FALSE) ; } else { // create events for detection of reading and write to com port sprintf(tempstr,"COMM_READ_OVERLAPPED_EVENT_FOR_%s",port_zstr); osRead[portnum].hEvent = CreateEvent(NULL,TRUE,FALSE,tempstr); sprintf(tempstr,"COMM_WRITE_OVERLAPPED_EVENT_FOR_%s",port_zstr); osWrite[portnum].hEvent = CreateEvent(NULL,TRUE,FALSE,tempstr); // get any early notifications SetCommMask(ComID[portnum], EV_RXCHAR | EV_TXEMPTY | EV_ERR | EV_BREAK); // setup device buffers SetupComm(ComID[portnum], 2048, 2048); // purge any information in the buffer PurgeComm(ComID[portnum], PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); // set up for overlapped non-blocking I/O CommTimeOuts.ReadIntervalTimeout = 0; CommTimeOuts.ReadTotalTimeoutMultiplier = 20; CommTimeOuts.ReadTotalTimeoutConstant = 40; CommTimeOuts.WriteTotalTimeoutMultiplier = 20; CommTimeOuts.WriteTotalTimeoutConstant = 40; SetCommTimeouts(ComID[portnum], &CommTimeOuts); // setup the com port GetCommState(ComID[portnum], &dcb); dcb.BaudRate = CBR_9600; // current baud rate dcb.fBinary = TRUE; // binary mode, no EOF check dcb.fParity = FALSE; // enable parity checking dcb.fOutxCtsFlow = FALSE; // CTS output flow control dcb.fOutxDsrFlow = FALSE; // DSR output flow control dcb.fDtrControl = DTR_CONTROL_ENABLE; // DTR flow control type dcb.fDsrSensitivity = FALSE; // DSR sensitivity dcb.fTXContinueOnXoff = TRUE; // XOFF continues Tx dcb.fOutX = FALSE; // XON/XOFF out flow control dcb.fInX = FALSE; // XON/XOFF in flow control dcb.fErrorChar = FALSE; // enable error replacement dcb.fNull = FALSE; // enable null stripping dcb.fRtsControl = RTS_CONTROL_ENABLE; // RTS flow control dcb.fAbortOnError = FALSE; // abort reads/writes on error dcb.XonLim = 0; // transmit XON threshold dcb.XoffLim = 0; // transmit XOFF threshold dcb.ByteSize = 8; // number of bits/byte, 4-8 dcb.Parity = NOPARITY; // 0-4=no,odd,even,mark,space dcb.StopBits = ONESTOPBIT; // 0,1,2 = 1, 1.5, 2 dcb.XonChar = 0; // Tx and Rx XON character dcb.XoffChar = 1; // Tx and Rx XOFF character dcb.ErrorChar = 0; // error replacement character dcb.EofChar = 0; // end of input character dcb.EvtChar = 0; // received event character fRetVal = SetCommState(ComID[portnum], &dcb); } // check if successfull if (!fRetVal) { CloseHandle(ComID[portnum]); CloseHandle(osRead[portnum].hEvent); CloseHandle(osWrite[portnum].hEvent); ComID[portnum] = 0; OWERROR(OWERROR_SYSTEM_RESOURCE_INIT_FAILED); } return (fRetVal); } //--------------------------------------------------------------------------- // Closes the connection to the port. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // void CloseCOM(int portnum) { // disable event notification and wait for thread // to halt SetCommMask(ComID[portnum], 0); // drop DTR EscapeCommFunction(ComID[portnum], CLRDTR); // purge any outstanding reads/writes and close device handle PurgeComm(ComID[portnum], PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); CloseHandle(ComID[portnum]); CloseHandle(osRead[portnum].hEvent); CloseHandle(osWrite[portnum].hEvent); ComID[portnum] = 0; } //--------------------------------------------------------------------------- // Flush the rx and tx buffers // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // void FlushCOM(int portnum) { // purge any information in the buffer PurgeComm(ComID[portnum], PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); } //-------------------------------------------------------------------------- // Write an array of bytes to the COM port, verify that it was // sent out. Assume that baud rate has been set. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'outlen' - number of bytes to write to COM port // 'outbuf' - pointer ot an array of bytes to write // // Returns: TRUE(1) - success // FALSE(0) - failure // SMALLINT WriteCOM(int portnum, int outlen, uchar *outbuf) { BOOL fWriteStat; DWORD dwBytesWritten=0; DWORD ler=0,to; // calculate a timeout to = 20 * outlen + 60; // reset the write event ResetEvent(osWrite[portnum].hEvent); // write the byte fWriteStat = WriteFile(ComID[portnum], (LPSTR) &outbuf[0], outlen, &dwBytesWritten, &osWrite[portnum] ); // check for an error if (!fWriteStat) ler = GetLastError(); // if not done writting then wait if (!fWriteStat && ler == ERROR_IO_PENDING) { WaitForSingleObject(osWrite[portnum].hEvent,to); // verify all is written correctly fWriteStat = GetOverlappedResult(ComID[portnum], &osWrite[portnum], &dwBytesWritten, FALSE); } // check results of write if (!fWriteStat || (dwBytesWritten != (DWORD)outlen)) return 0; else return 1; } //-------------------------------------------------------------------------- // Read an array of bytes to the COM port, verify that it was // sent out. Assume that baud rate has been set. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'inlen' - number of bytes to read from COM port // 'inbuf' - pointer to a buffer to hold the incomming bytes // // Returns: number of characters read // int ReadCOM(int portnum, int inlen, uchar *inbuf) { DWORD dwLength=0; BOOL fReadStat; DWORD ler=0,to; // calculate a timeout to = 20 * inlen + 60; // reset the read event ResetEvent(osRead[portnum].hEvent); // read fReadStat = ReadFile(ComID[portnum], (LPSTR) &inbuf[0], inlen, &dwLength, &osRead[portnum]) ; // check for an error if (!fReadStat) ler = GetLastError(); // if not done writing then wait if (!fReadStat && ler == ERROR_IO_PENDING) { // wait until everything is read WaitForSingleObject(osRead[portnum].hEvent,to); // verify all is read correctly fReadStat = GetOverlappedResult(ComID[portnum], &osRead[portnum], &dwLength, FALSE); } // check results if (fReadStat) return dwLength; else return 0; } //-------------------------------------------------------------------------- // Send a break on the com port for at least 2 ms // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // void BreakCOM(int portnum) { // start the reset pulse SetCommBreak(ComID[portnum]); // sleep Sleep(2); // clear the break ClearCommBreak(ComID[portnum]); } //-------------------------------------------------------------------------- // Set the baud rate on the com port. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'new_baud' - new baud rate defined as // PARMSET_9600 0x00 // PARMSET_19200 0x02 // PARMSET_57600 0x04 // PARMSET_115200 0x06 // void SetBaudCOM(int portnum, uchar new_baud) { DCB dcb; // get the current com port state GetCommState(ComID[portnum], &dcb); // change just the baud rate switch (new_baud) { case PARMSET_115200: dcb.BaudRate = CBR_115200; break; case PARMSET_57600: dcb.BaudRate = CBR_57600; break; case PARMSET_19200: dcb.BaudRate = CBR_19200; break; case PARMSET_9600: default: dcb.BaudRate = CBR_9600; break; } // restore to set the new baud rate SetCommState(ComID[portnum], &dcb); } //-------------------------------------------------------------------------- // Description: // Delay for at least 'len' ms // void msDelay(int len) { Sleep(len); } //-------------------------------------------------------------------------- // 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) { return GetTickCount(); } digitemp-3.6.0+dfsg1/userial/ds9097u/0000755000175000017500000000000011055620247015620 5ustar ryanryandigitemp-3.6.0+dfsg1/userial/ds9097u/ownetu.c0000644000175000017500000005111010632073746017311 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // owNetU.C - Network functions for 1-Wire Net devices // using the DS2480/DS2480B (U) serial interface chip. // // Version: 2.01 // // 1.02 -> 1.03 Removed caps in #includes for Linux capatibility // 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for // multiple ports. // 2.00 -> 2.01 Added error handling. Added circular-include check. // 2.01 -> 2.10 Added raw memory error handling and SMALLINT // 2.10 -> 3.00 Added memory bank functionality // Added file I/O operations // #include "ownet.h" #include "ds2480.h" // external functions defined in owllu.c extern SMALLINT owTouchReset(int); extern SMALLINT owTouchBit(int,SMALLINT); extern SMALLINT owWriteByte(int,SMALLINT); extern SMALLINT owReadByte(int); extern SMALLINT owSpeed(int,SMALLINT); extern SMALLINT owLevel(int,SMALLINT); // external functions defined in owltrnu.c extern SMALLINT owBlock(int,SMALLINT,uchar *,SMALLINT); // external COM functions defined in system specific link file extern SMALLINT WriteCOM(int,int,uchar *); extern int ReadCOM(int,int,uchar *); extern void FlushCOM(int); // external functions defined in ds2480ut.c extern SMALLINT DS2480Detect(int); // external functions defined in crcutil.c extern void setcrc8(int,uchar); extern uchar docrc8(int,uchar); // exportable functions defined in ownetu.c SMALLINT owFirst(int,SMALLINT,SMALLINT); SMALLINT owNext(int,SMALLINT,SMALLINT); void owSerialNum(int,uchar *,SMALLINT); void owFamilySearchSetup(int,SMALLINT); void owSkipFamily(int); SMALLINT owAccess(int); SMALLINT owVerify(int,SMALLINT); SMALLINT owOverdriveAccess(int); // local functions defined in ownetu.c SMALLINT bitacc(SMALLINT,SMALLINT,SMALLINT,uchar *); // global variables for this module to hold search state information static int LastDiscrepancy[MAX_PORTNUM]; static int LastFamilyDiscrepancy[MAX_PORTNUM]; static uchar LastDevice[MAX_PORTNUM]; uchar SerialNum[MAX_PORTNUM][8]; // external globals extern int UMode[MAX_PORTNUM]; extern SMALLINT USpeed[MAX_PORTNUM]; //-------------------------------------------------------------------------- // The 'owFirst' finds the first device on the 1-Wire Net This function // contains one parameter 'alarm_only'. When // 'alarm_only' 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. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'do_reset' - TRUE (1) perform reset before search, FALSE (0) do not // perform reset before search. // 'alarm_only' - 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 1-Wire Net. // SMALLINT owFirst(int portnum, SMALLINT do_reset, SMALLINT alarm_only) { // reset the search state LastDiscrepancy[portnum] = 0; LastDevice[portnum] = FALSE; LastFamilyDiscrepancy[portnum] = 0; return owNext(portnum, do_reset, alarm_only); } //-------------------------------------------------------------------------- // The 'owNext' function does a general search. This function // continues from the previos search state. The search state // can be reset by using the 'owFirst' function. // This function contains one parameter 'alarm_only'. // When 'alarm_only' 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. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'do_reset' - TRUE (1) perform reset before search, FALSE (0) do not // perform reset before search. // 'alarm_only' - 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 1-Wire Net. // SMALLINT owNext(int portnum, SMALLINT do_reset, SMALLINT alarm_only) { uchar tmp_last_desc,pos; uchar tmp_serial_num[8]; uchar readbuffer[20],sendpacket[40]; uchar i,sendlen=0; uchar lastcrc8; // if the last call was the last one if (LastDevice[portnum]) { // reset the search LastDiscrepancy[portnum] = 0; LastDevice[portnum] = FALSE; LastFamilyDiscrepancy[portnum] = 0; return FALSE; } // check if reset first is requested if (do_reset) { // reset the 1-wire // if there are no parts on 1-wire, return FALSE if (!owTouchReset(portnum)) { // reset the search LastDiscrepancy[portnum] = 0; LastFamilyDiscrepancy[portnum] = 0; OWERROR(OWERROR_NO_DEVICES_ON_NET); 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[portnum] != MODSEL_DATA) { UMode[portnum] = MODSEL_DATA; sendpacket[sendlen++] = MODE_DATA; } // search command if (alarm_only) sendpacket[sendlen++] = 0xEC; // issue the alarming search command else sendpacket[sendlen++] = 0xF0; // issue the search command // change back to command mode UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; // search mode on sendpacket[sendlen++] = (uchar)(CMD_COMM | FUNCTSEL_SEARCHON | USpeed[portnum]); // change back to data mode UMode[portnum] = MODSEL_DATA; sendpacket[sendlen++] = MODE_DATA; // set the temp Last Descrep to none tmp_last_desc = 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[portnum] != 0xFF) { // set the bits in the added buffer for (i = 0; i < 64; i++) { // before last discrepancy if (i < (LastDiscrepancy[portnum] - 1)) bitacc(WRITE_FUNCTION, bitacc(READ_FUNCTION,0,i,&SerialNum[portnum][0]), (short)(i * 2 + 1), &sendpacket[pos]); // at last discrepancy else if (i == (LastDiscrepancy[portnum] - 1)) bitacc(WRITE_FUNCTION,1, (short)(i * 2 + 1), &sendpacket[pos]); // after last discrepancy so leave zeros } } // change back to command mode UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; // search OFF sendpacket[sendlen++] = (uchar)(CMD_COMM | FUNCTSEL_SEARCHOFF | USpeed[portnum]); // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum,sendlen,sendpacket)) { // read back the 1 byte response if (ReadCOM(portnum,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, &tmp_serial_num[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)) { tmp_last_desc = i + 1; // check LastFamilyDiscrepancy if (i < 8) LastFamilyDiscrepancy[portnum] = i + 1; } } // do dowcrc setcrc8(portnum,0); for (i = 0; i < 8; i++) lastcrc8 = docrc8(portnum,tmp_serial_num[i]); // check results if ((lastcrc8 != 0) || (LastDiscrepancy[portnum] == 63) || (tmp_serial_num[0] == 0)) { // error during search // reset the search LastDiscrepancy[portnum] = 0; LastDevice[portnum] = FALSE; LastFamilyDiscrepancy[portnum] = 0; OWERROR(OWERROR_SEARCH_ERROR); return FALSE; } // successful search else { // check for lastone if ((tmp_last_desc == LastDiscrepancy[portnum]) || (tmp_last_desc == 0xFF)) LastDevice[portnum] = TRUE; // copy the SerialNum to the buffer for (i = 0; i < 8; i++) SerialNum[portnum][i] = tmp_serial_num[i]; // set the count LastDiscrepancy[portnum] = tmp_last_desc; return TRUE; } } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); // an error occured so re-sync with DS2480 DS2480Detect(portnum); // reset the search LastDiscrepancy[portnum] = 0; LastDevice[portnum] = FALSE; LastFamilyDiscrepancy[portnum] = 0; return FALSE; } //-------------------------------------------------------------------------- // The 'owSerialNum' function either reads or sets the SerialNum buffer // that is used in the search functions 'owFirst' and 'owNext'. // This function contains two parameters, 'serialnum_buf' is a pointer // to a buffer provided by the caller. 'serialnum_buf' should point to // an array of 8 unsigned chars. The second parameter is a flag called // 'do_read' 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. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'serialnum_buf' - buffer to that contains the serial number to set // when do_read = FALSE (0) and buffer to get the serial // number when do_read = TRUE (1). // 'do_read' - flag to indicate reading (1) or setting (0) the current // serial number. // void owSerialNum(int portnum, uchar *serialnum_buf, SMALLINT do_read) { uchar i; // read the internal buffer and place in 'serialnum_buf' if (do_read) { for (i = 0; i < 8; i++) serialnum_buf[i] = SerialNum[portnum][i]; } // set the internal buffer from the data in 'serialnum_buf' else { for (i = 0; i < 8; i++) SerialNum[portnum][i] = serialnum_buf[i]; } } //-------------------------------------------------------------------------- // Setup the search algorithm to find a certain family of devices // the next time a search function is called 'owNext'. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'search_family' - family code type to set the search algorithm to find // next. // void owFamilySearchSetup(int portnum, SMALLINT search_family) { uchar i; // set the search state to find search_family type devices SerialNum[portnum][0] = search_family; for (i = 1; i < 8; i++) SerialNum[portnum][i] = 0; LastDiscrepancy[portnum] = 64; LastDevice[portnum] = FALSE; } //-------------------------------------------------------------------------- // Set the current search state to skip the current family code. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // void owSkipFamily(int portnum) { // set the Last discrepancy to last family discrepancy LastDiscrepancy[portnum] = LastFamilyDiscrepancy[portnum]; // check for end of list if (LastDiscrepancy[portnum] == 0) LastDevice[portnum] = TRUE; } //-------------------------------------------------------------------------- // The 'owAccess' 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. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // 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. // SMALLINT owAccess(int portnum) { uchar sendpacket[9]; uchar i; // reset the 1-wire if (owTouchReset(portnum)) { // create a buffer to use with block function // match Serial Number command 0x55 sendpacket[0] = 0x55; // Serial Number for (i = 1; i < 9; i++) sendpacket[i] = SerialNum[portnum][i-1]; // send/recieve the transfer buffer if (owBlock(portnum,FALSE,sendpacket,9)) { // verify that the echo of the writes was correct for (i = 1; i < 9; i++) if (sendpacket[i] != SerialNum[portnum][i-1]) return FALSE; if (sendpacket[0] != 0x55) { OWERROR(OWERROR_WRITE_VERIFY_FAILED); return FALSE; } else return TRUE; } else OWERROR(OWERROR_BLOCK_FAILED); } else OWERROR(OWERROR_NO_DEVICES_ON_NET); // reset or match echo failed return FALSE; } //---------------------------------------------------------------------- // The function 'owVerify' verifies that the current device // is in contact with the 1-Wire Net. // Using the find alarm command 0xEC will verify that the device // is in contact with the 1-Wire Net and is in an 'alarm' state. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'alarm_only' - 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 1-Wire Net // with alarm_only == FALSE // or verified to be on the 1-Wire Net // AND in an alarm state when // alarm_only == TRUE. // FALSE (0): the 1-Wire device was not on the // 1-Wire Net or if alarm_only // == TRUE, the device may be on the // 1-Wire Net but in a non-alarm state. // SMALLINT owVerify(int portnum, SMALLINT alarm_only) { uchar i,sendlen=0,goodbits=0,cnt=0,s,tst; uchar sendpacket[50]; // construct the search rom if (alarm_only) sendpacket[sendlen++] = 0xEC; // issue the alarming search command else sendpacket[sendlen++] = 0xF0; // issue the search command // set all bits at first for (i = 1; i <= 24; i++) sendpacket[sendlen++] = 0xFF; // now set or clear apropriate bits for search for (i = 0; i < 64; i++) bitacc(WRITE_FUNCTION,bitacc(READ_FUNCTION,0,i,&SerialNum[portnum][0]),(int)((i+1)*3-1),&sendpacket[1]); // send/recieve the transfer buffer if (owBlock(portnum,TRUE,sendpacket,sendlen)) { // check results to see if it was a success for (i = 0; i < 192; i += 3) { tst = (bitacc(READ_FUNCTION,0,i,&sendpacket[1]) << 1) | bitacc(READ_FUNCTION,0,(int)(i+1),&sendpacket[1]); s = bitacc(READ_FUNCTION,0,cnt++,&SerialNum[portnum][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; } else OWERROR(OWERROR_BLOCK_FAILED); // 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. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE: If the device is present on the 1-Wire Net 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. // SMALLINT owOverdriveAccess(int portnum) { uchar sendpacket[8]; uchar i, bad_echo = FALSE; // make sure normal level owLevel(portnum,MODE_NORMAL); // force to normal communication speed owSpeed(portnum,MODE_NORMAL); // call the 1-Wire Net reset function if (owTouchReset(portnum)) { // send the match command 0x69 if (owWriteByte(portnum,0x69)) { // switch to overdrive communication speed owSpeed(portnum,MODE_OVERDRIVE); // create a buffer to use with block function // Serial Number for (i = 0; i < 8; i++) sendpacket[i] = SerialNum[portnum][i]; // send/recieve the transfer buffer if (owBlock(portnum,FALSE,sendpacket,8)) { // verify that the echo of the writes was correct for (i = 0; i < 8; i++) if (sendpacket[i] != SerialNum[portnum][i]) bad_echo = TRUE; // if echo ok then success if (!bad_echo) return TRUE; else OWERROR(OWERROR_WRITE_VERIFY_FAILED); } else OWERROR(OWERROR_BLOCK_FAILED); } else OWERROR(OWERROR_WRITE_BYTE_FAILED); } else OWERROR(OWERROR_NO_DEVICES_ON_NET); // failure, force back to normal communication speed owSpeed(portnum,MODE_NORMAL); return FALSE; } //-------------------------------------------------------------------------- // 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 // SMALLINT bitacc(SMALLINT op, SMALLINT state, SMALLINT loc, uchar *buf) { SMALLINT 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); } digitemp-3.6.0+dfsg1/userial/ds9097u/linuxlnk.c0000644000175000017500000003125610632073746017645 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // linuxlnk.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: 2.01 // History: 1.02 -> 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() // // 1.03 -> 2.00 Support for multiple ports. Include "ownet.h". Use // 'uchar'. Reorder functions. Provide correct // return values to OpenCOM. Replace 'makeraw' call. // Should now be POSIX. // 2.00 -> 2.01 Added support for owError library. // #include #include #include #include #include #include #include #include #include #include "ds2480.h" #include "ownet.h" /* exportable functions */ SMALLINT OpenCOM(int, char*); SMALLINT WriteCOM(int, int, uchar*); void CloseCOM(int); void FlushCOM(int); int ReadCOM(int, int, uchar*); void BreakCOM(int); void SetBaudCOM(int, int); void msDelay(int); long msGettick(void); // LinuxLNK global int fd[MAX_PORTNUM]; struct termios origterm; //--------------------------------------------------------------------------- // Attempt to open a com port. // Set the starting baud rate to 9600. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number provided will // be used to indicate the port number desired when calling // all other functions in this library. // // 'port_zstr' - zero terminate port name. For this platform // use format COMX where X is the port number. // // // Returns: TRUE(1) - success, COM port opened // FALSE(0) - failure, could not open specified port // SMALLINT OpenCOM(int portnum, char *port_zstr) { struct termios t; // see man termios - declared as above int rc; fd[portnum] = open(port_zstr, O_RDWR|O_NONBLOCK); if (fd[portnum]<0) { OWERROR(OWERROR_GET_SYSTEM_RESOURCE_FAILED); return FALSE; // changed (2.00), used to return fd; } rc = tcgetattr (fd[portnum], &t); if (rc < 0) { int tmp; tmp = errno; close(fd[portnum]); errno = tmp; OWERROR(OWERROR_SYSTEM_RESOURCE_INIT_FAILED); return FALSE; // changed (2.00), used to return rc; } cfsetospeed(&t, B9600); cfsetispeed (&t, B9600); // Get terminal parameters. (2.00) removed raw tcgetattr(fd[portnum],&t); // Save original settings. origterm = t; // Set to non-canonical mode, and no RTS/CTS handshaking t.c_iflag &= ~(BRKINT|ICRNL|IGNCR|INLCR|INPCK|ISTRIP|IXON|IXOFF|PARMRK); t.c_iflag |= IGNBRK|IGNPAR; t.c_oflag &= ~(OPOST); t.c_cflag &= ~(CRTSCTS|CSIZE|HUPCL|PARENB); t.c_cflag |= (CLOCAL|CS8|CREAD); t.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ICANON|IEXTEN|ISIG); t.c_cc[VMIN] = 0; t.c_cc[VTIME] = 3; rc = tcsetattr(fd[portnum], TCSAFLUSH, &t); tcflush(fd[portnum],TCIOFLUSH); if (rc < 0) { int tmp; tmp = errno; close(fd[portnum]); errno = tmp; OWERROR(OWERROR_SYSTEM_RESOURCE_INIT_FAILED); return FALSE; // changed (2.00), used to return rc; } return TRUE; // changed (2.00), used to return fd; } //--------------------------------------------------------------------------- // Closes the connection to the port. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // void CloseCOM(int portnum) { // restore tty settings tcsetattr(fd[portnum], TCSAFLUSH, &origterm); FlushCOM(portnum); close(fd[portnum]); } //-------------------------------------------------------------------------- // Write an array of bytes to the COM port, verify that it was // sent out. Assume that baud rate has been set. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number provided will // be used to indicate the port number desired when calling // all other functions in this library. // Returns 1 for success and 0 for failure // SMALLINT WriteCOM(int portnum, int outlen, uchar *outbuf) { long count = outlen; int i = write(fd[portnum], outbuf, outlen); tcdrain(fd[portnum]); 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. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'outlen' - number of bytes to write to COM port // 'outbuf' - pointer ot an array of bytes to write // // Returns: Number of bytes actually read // int ReadCOM(int portnum, int inlen, uchar *inbuf) { fd_set filedescr; struct timeval tval; int cnt; int sel; int msec = 0; extern int global_msec, global_msec_max; // loop to wait until each byte is available and read it for (cnt = 0; cnt < inlen; cnt++) { if( msec < global_msec ) msec = global_msec; // set a descriptor to wait for a character available FD_ZERO(&filedescr); FD_SET(fd[portnum],&filedescr); // set initial timeout to global_msec ms tval.tv_sec = 1; tval.tv_usec = 1000 * msec; // if byte available read or return bytes read sel = select(fd[portnum]+1,&filedescr,NULL,NULL,&tval); if ( sel > 0 ) { if (read(fd[portnum],&inbuf[cnt],1) != 1) { /* Received something, return it */ return cnt; } } else if( sel == 0 ) { /* We timed out waiting for a character, so increase the limit */ global_msec++; cnt = -1; #ifdef DEBUG_USERIAL fprintf(stderr, "Increasing delay to %ld\n", global_msec * 1000 ); #endif /* DEBUG_USERIAL */ /* don't go too high, just return an error (0) */ if( global_msec > global_msec_max ) return 0; } else { return cnt; } /* select if */ } /* count loop */ // success, so return desired length return inlen; } //--------------------------------------------------------------------------- // Description: // flush the rx and tx buffers // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // void FlushCOM(int portnum) { tcflush(fd[portnum], TCIOFLUSH); } //-------------------------------------------------------------------------- // Description: // Send a break on the com port for at least 2 ms // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // void BreakCOM(int portnum) { int duration = 0; // see man termios break may be tcsendbreak(fd[portnum], duration); // too long } //-------------------------------------------------------------------------- // Set the baud rate on the com port. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'new_baud' - new baud rate defined as // PARMSET_9600 0x00 // PARMSET_19200 0x02 // PARMSET_57600 0x04 // PARMSET_115200 0x06 // void SetBaudCOM(int portnum, int new_baud) { struct termios t; int rc; speed_t baud=B9600; // read the attribute structure rc = tcgetattr(fd[portnum], &t); if (rc < 0) { close(fd[portnum]); 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: baud = B57600; break; case PARMSET_115200: baud = B115200; break; } // set baud in structure cfsetospeed(&t, baud); cfsetispeed(&t, baud); // change baud on port rc = tcsetattr(fd[portnum], TCSAFLUSH, &t); if (rc < 0) close(fd[portnum]); } //-------------------------------------------------------------------------- // 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; } //-------------------------------------------------------------------------- // 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); } digitemp-3.6.0+dfsg1/userial/ds9097u/ds2480ut.c0000644000175000017500000002122710632073746017273 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // ds2480ut.c - DS2480B utility functions. // // Version: 2.01 // // 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 // 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for // multiple ports. Changed W1LT to 8us. // 2.00 -> 2.01 Added error handling. Added circular-include check. // 2.01 -> 2.10 Added raw memory error handling and SMALLINT // 2.10 -> 3.00 Added memory bank functionality // Added file I/O operations // #include "ownet.h" #include "ds2480.h" // external COM functions defined in system specific link file extern SMALLINT WriteCOM(int,int,uchar *); extern void FlushCOM(int); extern int ReadCOM(int,int,uchar *); extern void BreakCOM(int); extern void SetBaudCOM(int,uchar); extern void msDelay(int); // exportable functions defined in ds2480ut.c SMALLINT DS2480Detect(int); SMALLINT DS2480ChangeBaud(int,uchar); SMALLINT DS2480Try( int portnum ); // global DS2480B state SMALLINT ULevel[MAX_PORTNUM]; // current DS2480B 1-Wire Net level SMALLINT UBaud[MAX_PORTNUM]; // current DS2480B baud rate SMALLINT UMode[MAX_PORTNUM]; // current DS2480B command or data mode state SMALLINT USpeed[MAX_PORTNUM]; // current DS2480B 1-Wire Net communication speed //--------------------------------------------------------------------------- // Attempt to resyc and detect a DS2480B // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE - DS2480B detected successfully // FALSE - Could not detect DS2480B // SMALLINT DS2480Detect(int portnum) { int retry = 0; while( retry++ < 10 ) { if( DS2480Try( portnum ) == TRUE ) return TRUE; } return FALSE; } SMALLINT DS2480Try( int portnum ) { uchar sendpacket[10],readbuffer[10]; uchar sendlen=0; // reset modes UMode[portnum] = MODSEL_COMMAND; UBaud[portnum] = PARMSET_9600; USpeed[portnum] = SPEEDSEL_FLEX; // set the baud rate to 9600 SetBaudCOM(portnum,(uchar)UBaud[portnum]); // send a break to reset the DS2480 BreakCOM(portnum); // delay to let line settle msDelay(2); // flush the buffers FlushCOM(portnum); // send the timing byte sendpacket[0] = 0xC1; if (WriteCOM(portnum,1,sendpacket) != 1) { OWERROR(OWERROR_WRITECOM_FAILED); return FALSE; } // delay to let line settle msDelay(4); // set the FLEX configuration parameters // default PDSRC = 1.37Vus sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_SLEW | PARMSET_Slew1p37Vus; // default W1LT = 10us sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_WRITE1LOW | PARMSET_Write10us; // default DSO/WORT = 8us sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_SAMPLEOFFSET | PARMSET_SampOff8us; // 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[portnum] | BITPOL_ONE; #ifdef DEBUG_USERIAL { int i; printf("sendpacket: "); for(i=0;i<5;i++) printf("%02X ", sendpacket[i] ); printf("\n"); } #endif /* DEBUG_USERIAL */ // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum,sendlen,sendpacket)) { // read back the response if (ReadCOM(portnum,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[portnum]) && ((readbuffer[4] & 0xF0) == 0x90) && ((readbuffer[4] & 0x0C) == UBaud[portnum])) { #ifdef DEBUG_USERIAL int i; printf("readbuffer: "); for(i=0;i<5;i++) printf("%02X ", readbuffer[i] ); printf("\n"); #endif /* DEBUG_USERIAL */ return TRUE; } else { #ifdef DEBUG_USERIAL int i; printf("readbuffer: "); for(i=0;i<5;i++) printf("%02X ", readbuffer[i] ); printf("\n"); #endif /* DEBUG_USERIAL */ OWERROR(OWERROR_DS2480_BAD_RESPONSE); } } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); return FALSE; } //--------------------------------------------------------------------------- // Change the DS2480B from the current baud rate to the new baud rate. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'newbaud' - the new baud rate to change to, defined as: // PARMSET_9600 0x00 // PARMSET_19200 0x02 // PARMSET_57600 0x04 // PARMSET_115200 0x06 // // Returns: current DS2480B baud rate. // SMALLINT DS2480ChangeBaud(int portnum, uchar newbaud) { uchar rt=FALSE; uchar readbuffer[5],sendpacket[5],sendpacket2[5]; uchar sendlen=0,sendlen2=0; // see if diffenent then current baud rate if (UBaud[portnum] == newbaud) return UBaud[portnum]; else { // build the command packet // check if correct mode if (UMode[portnum] != MODSEL_COMMAND) { UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; } // build the command sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_BAUDRATE | newbaud; // flush the buffers FlushCOM(portnum); // send the packet if (!WriteCOM(portnum,sendlen,sendpacket)) { OWERROR(OWERROR_WRITECOM_FAILED); rt = FALSE; } else { // make sure buffer is flushed msDelay(5); // change our baud rate SetBaudCOM(portnum,newbaud); UBaud[portnum] = 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(portnum); // send the packet if (WriteCOM(portnum,sendlen2,sendpacket2)) { // read back the 1 byte response if (ReadCOM(portnum,1,readbuffer) == 1) { // verify correct baud if (((readbuffer[0] & 0x0E) == (sendpacket[sendlen-1] & 0x0E))) rt = TRUE; else OWERROR(OWERROR_DS2480_WRONG_BAUD); } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); } } // if lost communication with DS2480 then reset if (rt != TRUE) DS2480Detect(portnum); return UBaud[portnum]; } digitemp-3.6.0+dfsg1/userial/ds9097u/owtrnu.c0000644000175000017500000005025010632073746017332 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // owTranU.C - Transport functions for 1-Wire Net // using the DS2480B (U) serial interface chip. // // Version: 2.01 // // History: 1.02 -> 1.03 Removed caps in #includes for Linux capatibility // 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for // multiple ports. // 2.00 -> 2.01 Added support for owError library // 2.01 -> 2.10 Added SMALLINT for small processors and error // handling plus the raw memory utilities. // 2.10 -> 3.00 Added memory bank functionality // Added file I/O operations // #include "ownet.h" #include "ds2480.h" // external functions defined in owllu.c extern SMALLINT owTouchReset(int); extern SMALLINT owWriteByte(int,SMALLINT); extern SMALLINT owReadByte(int); extern SMALLINT owProgramPulse(int); // external network-level functions defined in owsesu.c extern SMALLINT owAccess(int); // external COM functions required defined in system specific link file extern SMALLINT WriteCOM(int,int,uchar *); extern int ReadCOM(int,int,uchar *); extern void FlushCOM(int); // external defined in ds2480ut.c extern SMALLINT DS2480Detect(int); extern SMALLINT UBaud[MAX_PORTNUM]; extern SMALLINT UMode[MAX_PORTNUM]; extern SMALLINT USpeed[MAX_PORTNUM]; extern uchar SerialNum[MAX_PORTNUM][8]; // external functions defined in crcutil.c extern void setcrc16(int,ushort); extern ushort docrc16(int,ushort); extern void setcrc8(int,uchar); extern uchar docrc8(int,uchar); // exportable functions defined in owtrnu.c SMALLINT owBlock(int,SMALLINT,uchar *,SMALLINT); SMALLINT owReadPacketStd(int,SMALLINT,int,uchar *); SMALLINT owWritePacketStd(int,int,uchar *,SMALLINT,SMALLINT,SMALLINT); SMALLINT owProgramByte(int,SMALLINT,int,SMALLINT,SMALLINT,SMALLINT); // local static functions static SMALLINT Write_Scratchpad(int,uchar *,int,SMALLINT); static SMALLINT Copy_Scratchpad(int,int,SMALLINT); //-------------------------------------------------------------------------- // The 'owBlock' transfers a block of data to and from the // 1-Wire Net with an optional reset at the begining of communication. // The result is returned in the same buffer. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'do_reset' - cause a owTouchReset to occure at the begining of // communication TRUE(1) or not FALSE(0) // 'tran_buf' - pointer to a block of unsigned // chars of length 'tran_len' that will be sent // to the 1-Wire Net // 'tran_len' - length in bytes to transfer // Supported devices: all // // Returns: TRUE (1) : The optional reset returned a valid // presence (do_reset == TRUE) or there // was no reset required. // FALSE (0): The reset did not return a valid prsence // (do_reset == TRUE). // // The maximum tran_length is 64 // SMALLINT owBlock(int portnum, SMALLINT do_reset, uchar *tran_buf, SMALLINT tran_len) { uchar sendpacket[150]; uchar sendlen=0,pos,i; // check for a block too big if (tran_len > 64) { OWERROR(OWERROR_BLOCK_TOO_BIG); return FALSE; } // check if need to do a owTouchReset first if (do_reset) { if (!owTouchReset(portnum)) { OWERROR(OWERROR_NO_DEVICES_ON_NET); return FALSE; } } // construct the packet to send to the DS2480 // check if correct mode if (UMode[portnum] != MODSEL_DATA) { UMode[portnum] = MODSEL_DATA; sendpacket[sendlen++] = MODE_DATA; } // add the bytes to send pos = sendlen; for (i = 0; i < tran_len; i++) { sendpacket[sendlen++] = tran_buf[i]; // check for duplication of data that looks like COMMAND mode if (tran_buf[i] == MODE_COMMAND) sendpacket[sendlen++] = tran_buf[i]; } // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum,sendlen,sendpacket)) { // read back the response if (ReadCOM(portnum,tran_len,tran_buf) == tran_len) return TRUE; else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); // an error occured so re-sync with DS2480 DS2480Detect(portnum); return FALSE; } //-------------------------------------------------------------------------- // Read a Universal Data Packet from a standard NVRAM iButton // and return it in the provided buffer. The page that the // packet resides on is 'start_page'. Note that this function is limited // to single page packets. The buffer 'read_buf' must be at least // 29 bytes long. // // The Universal Data Packet always start on page boundaries but // can end anywhere. The length is the number of data bytes not // including the length byte and the CRC16 bytes. There is one // length byte. The CRC16 is first initialized to the starting // page number. This provides a check to verify the page that // was intended is being read. The CRC16 is then calculated over // the length and data bytes. The CRC16 is then inverted and stored // low byte first followed by the high byte. // // Supported devices: DS1992, DS1993, DS1994, DS1995, DS1996, DS1982, // DS1985, DS1986, DS2407, and DS1971. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'do_access' - flag to indicate if an 'owAccess' should be // peformed at the begining of the read. This may // be FALSE (0) if the previous call was to read the // previous page (start_page-1). // 'start_page' - page number to start the read from // 'read_buf' - pointer to a location to store the data read // // Returns: >=0 success, number of data bytes in the buffer // -1 failed to read a valid UDP // // SMALLINT owReadPacketStd(int portnum, SMALLINT do_access, int start_page, uchar *read_buf) { uchar i,length,sendlen=0,head_len=0; uchar sendpacket[50]; ushort lastcrc16; // check if access header is done // (only use if in sequention read with one access at begining) if (do_access) { // match command sendpacket[sendlen++] = 0x55; for (i = 0; i < 8; i++) sendpacket[sendlen++] = SerialNum[portnum][i]; // read memory command sendpacket[sendlen++] = 0xF0; // write the target address sendpacket[sendlen++] = ((start_page << 5) & 0xFF); sendpacket[sendlen++] = (start_page >> 3); // check for DS1982 exception (redirection byte) if (SerialNum[portnum][0] == 0x09) sendpacket[sendlen++] = 0xFF; // record the header length head_len = sendlen; } // read the entire page length byte for (i = 0; i < 32; i++) sendpacket[sendlen++] = 0xFF; // send/recieve the transfer buffer if (owBlock(portnum,do_access,sendpacket,sendlen)) { // seed crc with page number setcrc16(portnum,(ushort)start_page); // attempt to read UDP from sendpacket length = sendpacket[head_len]; docrc16(portnum,(ushort)length); // verify length is not too large if (length <= 29) { // loop to read packet including CRC for (i = 0; i < length; i++) { read_buf[i] = sendpacket[i+1+head_len]; docrc16(portnum,read_buf[i]); } // read and compute the CRC16 docrc16(portnum,sendpacket[i+1+head_len]); lastcrc16 = docrc16(portnum,sendpacket[i+2+head_len]); // verify the CRC16 is correct if (lastcrc16 == 0xB001) return length; // return number of byte in record else OWERROR(OWERROR_CRC_FAILED); } else OWERROR(OWERROR_INCORRECT_CRC_LENGTH); } else OWERROR(OWERROR_BLOCK_FAILED); // failed block or incorrect CRC return -1; } //-------------------------------------------------------------------------- // Write a Universal Data Packet onto a standard NVRAM 1-Wire device // on page 'start_page'. This function is limited to UDPs that // fit on one page. The data to write is provided as a buffer // 'write_buf' with a length 'write_len'. // // The Universal Data Packet always start on page boundaries but // can end anywhere. The length is the number of data bytes not // including the length byte and the CRC16 bytes. There is one // length byte. The CRC16 is first initialized to the starting // page number. This provides a check to verify the page that // was intended is being read. The CRC16 is then calculated over // the length and data bytes. The CRC16 is then inverted and stored // low byte first followed by the high byte. // // Supported devices: is_eprom=0 // DS1992, DS1993, DS1994, DS1995, DS1996 // is_eprom=1, crc_type=0(CRC8) // DS1982 // is_eprom=1, crc_type=1(CRC16) // DS1985, DS1986, DS2407 // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'start_page' - page number to write packet to // 'write_buf' - pointer to buffer containing data to write // 'write_len' - number of data byte in write_buf // 'is_eprom' - flag set if device is an EPROM (1 EPROM, 0 NVRAM) // 'crc_type' - if is_eprom=1 then indicates CRC type // (0 CRC8, 1 CRC16) // // Returns: TRUE(1) success, packet written // FALSE(0) failure to write, contact lost or device locked // SMALLINT owWritePacketStd(int portnum, int start_page, uchar *write_buf, SMALLINT write_len, SMALLINT is_eprom, SMALLINT crc_type) { uchar construct_buffer[32]; uchar i,buffer_cnt=0,start_address,do_access; ushort lastcrc16=0; // check to see if data too long to fit on device if (write_len > 29) return FALSE; // seed crc with page number setcrc16(portnum,(ushort)start_page); // set length byte construct_buffer[buffer_cnt++] = (uchar)(write_len); docrc16(portnum,(ushort)write_len); // fill in the data to write for (i = 0; i < write_len; i++) { lastcrc16 = docrc16(portnum,write_buf[i]); construct_buffer[buffer_cnt++] = write_buf[i]; } // add the crc construct_buffer[buffer_cnt++] = (uchar)(~(lastcrc16 & 0xFF)); construct_buffer[buffer_cnt++] = (uchar)(~((lastcrc16 & 0xFF00) >> 8)); // check if not EPROM if (!is_eprom) { // write the page if (!Write_Scratchpad(portnum,construct_buffer,start_page,buffer_cnt)) { OWERROR(OWERROR_WRITE_SCRATCHPAD_FAILED); return FALSE; } // copy the scratchpad if (!Copy_Scratchpad(portnum,start_page,buffer_cnt)) { OWERROR(OWERROR_COPY_SCRATCHPAD_FAILED); return FALSE; } // copy scratch pad was good then success return TRUE; } // is EPROM else { // calculate the start address start_address = ((start_page >> 3) << 8) | ((start_page << 5) & 0xFF); do_access = TRUE; // loop to program each byte for (i = 0; i < buffer_cnt; i++) { if (owProgramByte(portnum,construct_buffer[i], start_address + i, 0x0F, crc_type, do_access) != construct_buffer[i]) { OWERROR(OWERROR_PROGRAM_BYTE_FAILED); return FALSE; } do_access = FALSE; } return TRUE; } } //-------------------------------------------------------------------------- // Write a byte to an EPROM 1-Wire device. // // Supported devices: crc_type=0(CRC8) // DS1982 // crc_type=1(CRC16) // DS1985, DS1986, DS2407 // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'write_byte' - byte to program // 'addr' - address of byte to program // 'write_cmd' - command used to write (0x0F reg mem, 0x55 status) // 'crc_type' - CRC used (0 CRC8, 1 CRC16) // 'do_access' - Flag to access device for each byte // (0 skip access, 1 do the access) // WARNING, only use do_access=0 if programing the NEXT // byte immediatly after the previous byte. // // Returns: >=0 success, this is the resulting byte from the program // effort // -1 error, device not connected or program pulse voltage // not available // SMALLINT owProgramByte(int portnum, SMALLINT write_byte, int addr, SMALLINT write_cmd, SMALLINT crc_type, SMALLINT do_access) { ushort lastcrc16; uchar lastcrc8; // optionally access the device if (do_access) { if (!owAccess(portnum)) { OWERROR(OWERROR_ACCESS_FAILED); return -1; } // send the write command if (!owWriteByte(portnum,write_cmd)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return -1; } // send the address if (!owWriteByte(portnum,addr & 0xFF) || !owWriteByte(portnum,addr >> 8)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return -1; } } // send the data to write if (!owWriteByte(portnum,write_byte)) { OWERROR(OWERROR_WRITE_BYTE_FAILED); return -1; } // read the CRC if (crc_type == 0) { // calculate CRC8 if (do_access) { setcrc8(portnum,0); docrc8(portnum,(uchar)write_cmd); docrc8(portnum,(uchar)(addr & 0xFF)); docrc8(portnum,(uchar)(addr >> 8)); } else setcrc8(portnum,(uchar)(addr & 0xFF)); docrc8(portnum,(uchar)write_byte); // read and calculate the read crc lastcrc8 = docrc8(portnum,(uchar)owReadByte(portnum)); // crc should now be 0x00 if (lastcrc8 != 0) { OWERROR(OWERROR_CRC_FAILED); return -1; } } else { // CRC16 if (do_access) { setcrc16(portnum,0); docrc16(portnum,(ushort)write_cmd); docrc16(portnum,(ushort)(addr & 0xFF)); docrc16(portnum,(ushort)(addr >> 8)); } else setcrc16(portnum,(ushort)addr); docrc16(portnum,(ushort)write_byte); // read and calculate the read crc docrc16(portnum,(ushort)owReadByte(portnum)); lastcrc16 = docrc16(portnum,(ushort)owReadByte(portnum)); // crc should now be 0xB001 if (lastcrc16 != 0xB001) { OWERROR(OWERROR_CRC_FAILED); return -1; } } // send the program pulse if (!owProgramPulse(portnum)) { OWERROR(OWERROR_PROGRAM_PULSE_FAILED); return -1; } // read back and return the resulting byte return owReadByte(portnum); } //-------------------------------------------------------------------------- // Write the scratchpad of a standard NVRam device such as the DS1992,3,4 // and verify its contents. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'write_buf' - pointer to buffer containing data to write // 'start_page' - page number to write packet to // 'write_len' - number of data byte in write_buf // // Returns: TRUE(1) success, the data was written and verified // FALSE(0) failure, the data could not be written // // SMALLINT Write_Scratchpad(int portnum, uchar *write_buf, int start_page, SMALLINT write_len) { uchar i,sendlen=0; uchar sendpacket[50]; // match command sendpacket[sendlen++] = 0x55; for (i = 0; i < 8; i++) sendpacket[sendlen++] = SerialNum[portnum][i]; // write scratchpad command sendpacket[sendlen++] = 0x0F; // write the target address sendpacket[sendlen++] = ((start_page << 5) & 0xFF); sendpacket[sendlen++] = (start_page >> 3); // write packet bytes for (i = 0; i < write_len; i++) sendpacket[sendlen++] = write_buf[i]; // send/recieve the transfer buffer if (owBlock(portnum,TRUE,sendpacket,sendlen)) { // now attempt to read back to check sendlen = 0; // match command sendpacket[sendlen++] = 0x55; for (i = 0; i < 8; i++) sendpacket[sendlen++] = SerialNum[portnum][i]; // read scratchpad command sendpacket[sendlen++] = 0xAA; // read the target address, offset and data for (i = 0; i < (write_len + 3); i++) sendpacket[sendlen++] = 0xFF; // send/recieve the transfer buffer if (owBlock(portnum,TRUE,sendpacket,sendlen)) { // check address and offset of scratchpad read if ((sendpacket[10] != ((start_page << 5) & 0xFF)) || (sendpacket[11] != (start_page >> 3)) || (sendpacket[12] != (write_len - 1))) { OWERROR(OWERROR_READ_VERIFY_FAILED); return FALSE; } // verify each data byte for (i = 0; i < write_len; i++) if (sendpacket[i+13] != write_buf[i]) { OWERROR(OWERROR_WRITE_VERIFY_FAILED); return FALSE; } // must have verified return TRUE; } else OWERROR(OWERROR_BLOCK_FAILED); } else OWERROR(OWERROR_BLOCK_FAILED); // failed a block tranfer return FALSE; } //-------------------------------------------------------------------------- // Copy the contents of the scratchpad to its intended nv ram page. The // page and length of the data is needed to build the authorization bytes // to copy. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to // indicate the symbolic port number. // 'start_page' - page number to write packet to // 'write_len' - number of data bytes that are being copied // // Returns: TRUE(1) success // FALSE(0) failure // SMALLINT Copy_Scratchpad(int portnum, int start_page, SMALLINT write_len) { uchar i,sendlen=0; uchar sendpacket[50]; // match command sendpacket[sendlen++] = 0x55; for (i = 0; i < 8; i++) sendpacket[sendlen++] = SerialNum[portnum][i]; // copy scratchpad command sendpacket[sendlen++] = 0x55; // write the target address sendpacket[sendlen++] = ((start_page << 5) & 0xFF); sendpacket[sendlen++] = (start_page >> 3); sendpacket[sendlen++] = write_len - 1; // read copy result sendpacket[sendlen++] = 0xFF; // send/recieve the transfer buffer if (owBlock(portnum,TRUE,sendpacket,sendlen)) { // check address and offset of scratchpad read if ((sendpacket[10] != ((start_page << 5) & 0xFF)) || (sendpacket[11] != (start_page >> 3)) || (sendpacket[12] != (write_len - 1)) || (sendpacket[13] & 0xF0)) { OWERROR(OWERROR_READ_VERIFY_FAILED); return FALSE; } else return TRUE; } else OWERROR(OWERROR_BLOCK_FAILED); // failed a block tranfer return FALSE; } digitemp-3.6.0+dfsg1/userial/ds9097u/ds2480.h0000644000175000017500000001627410632073746016735 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // DS2480.H - This file contains the DS2480B constants // // Version: 2.00 // // History: 1.02 -> 1.03 Make sure uchar is not defined twice. // // #ifndef __MC68K__ #include #ifndef _WIN32_WCE #include #endif #endif // Typedefs #ifndef OW_UCHAR #define OW_UCHAR typedef unsigned char uchar; #ifdef WIN32 #ifndef __CYGWIN__ //&& GCC //already defined in sys/types.h for cygwin typedef unsigned short ushort; #endif typedef unsigned long ulong; #endif #ifdef __MC68K__ typedef unsigned short ushort; typedef unsigned long ulong; #endif #ifdef WINCE typedef unsigned short ushort; typedef unsigned long ulong; #endif #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 // DS2480B 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 digitemp-3.6.0+dfsg1/userial/ds9097u/owllu.c0000644000175000017500000005572610632073746017153 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // owLLU.C - Link Layer 1-Wire Net functions using the DS2480/DS2480B (U) // serial interface chip. // // Version: 2.01 // // History: 1.00 -> 1.01 DS2480 version number now ignored in // owTouchReset. // 1.02 -> 1.03 Removed caps in #includes for Linux capatibility // Removed #include // Add #include "ownet.h" to define TRUE,FALSE // 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for // multiple ports. // 2.00 -> 2.01 Added error handling. Added circular-include check. // 2.01 -> 2.10 Added raw memory error handling and SMALLINT // 2.10 -> 3.00 Added memory bank functionality // Added file I/O operations // Added owReadBitPower and owWriteBytePower // #include "ownet.h" #include "ds2480.h" // external COM functions defined in system specific link file extern SMALLINT WriteCOM(int,int,uchar *); extern int ReadCOM(int,int,uchar *); extern void FlushCOM(int); extern void SetBaudCOM(int,uchar); extern void msDelay(int); // external DS2480 functions defined in ds2480ut.c extern SMALLINT DS2480Detect(int); extern SMALLINT DS2480ChangeBaud(int,uchar); // external globals extern SMALLINT ULevel[MAX_PORTNUM]; // current DS2480B 1-Wire Net level extern SMALLINT UBaud[MAX_PORTNUM]; // current DS2480B baud rate extern SMALLINT UMode[MAX_PORTNUM]; // current DS2480B command or data mode state extern SMALLINT USpeed[MAX_PORTNUM]; // current DS2480B 1-Wire Net communication speed // exportable functions defined in owllu.c SMALLINT owTouchReset(int); SMALLINT owTouchBit(int,SMALLINT); SMALLINT owTouchByte(int,SMALLINT); SMALLINT owWriteByte(int,SMALLINT); SMALLINT owReadByte(int); SMALLINT owSpeed(int,SMALLINT); SMALLINT owLevel(int,SMALLINT); SMALLINT owProgramPulse(int); SMALLINT owWriteBytePower(int,SMALLINT); SMALLINT owHasPowerDelivery(int); SMALLINT owHasProgramPulse(int); SMALLINT owHasOverDrive(int); SMALLINT owReadBitPower(int, SMALLINT); // local varable flag, true if program voltage available static SMALLINT ProgramAvailable[MAX_PORTNUM]; //-------------------------------------------------------------------------- // Reset all of the devices on the 1-Wire Net and return the result. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // 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,2, and 3 of the DS2480/DS2480B. // SMALLINT owTouchReset(int portnum) { uchar readbuffer[10],sendpacket[10]; uchar sendlen=0; // make sure normal level owLevel(portnum,MODE_NORMAL); // check if correct mode if (UMode[portnum] != MODSEL_COMMAND) { UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; } // construct the command sendpacket[sendlen++] = (uchar)(CMD_COMM | FUNCTSEL_RESET | USpeed[portnum]); // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum,sendlen,sendpacket)) { // read back the 1 byte response if (ReadCOM(portnum,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[portnum] = ((readbuffer[0] & 0x20) == 0x20); return TRUE; } else OWERROR(OWERROR_RESET_FAILED); } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); // an error occured so re-sync with DS2480 DS2480Detect(portnum); return FALSE; } //-------------------------------------------------------------------------- // Send 1 bit of communication to the 1-Wire Net and return the // result 1 bit read from the 1-Wire Net. The parameter 'sendbit' // least significant bit is used and the least significant bit // of the result is the return bit. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'sendbit' - the least significant bit is the bit to send // // Returns: 0: 0 bit read from sendbit // 1: 1 bit read from sendbit // SMALLINT owTouchBit(int portnum, SMALLINT sendbit) { uchar readbuffer[10],sendpacket[10]; uchar sendlen=0; // make sure normal level owLevel(portnum,MODE_NORMAL); // check if correct mode if (UMode[portnum] != MODSEL_COMMAND) { UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; } // construct the command sendpacket[sendlen] = (sendbit != 0) ? BITPOL_ONE : BITPOL_ZERO; sendpacket[sendlen++] |= CMD_COMM | FUNCTSEL_BIT | USpeed[portnum]; // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum,sendlen,sendpacket)) { // read back the response if (ReadCOM(portnum,1,readbuffer) == 1) { // interpret the response if (((readbuffer[0] & 0xE0) == 0x80) && ((readbuffer[0] & RB_BIT_MASK) == RB_BIT_ONE)) return 1; else return 0; } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); // an error occured so re-sync with DS2480 DS2480Detect(portnum); return 0; } //-------------------------------------------------------------------------- // Send 8 bits of communication to the 1-Wire Net and verify that the // 8 bits read from the 1-Wire Net is the same (write operation). // The parameter 'sendbyte' least significant 8 bits are used. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'sendbyte' - 8 bits to send (least significant byte) // // Returns: TRUE: bytes written and echo was the same // FALSE: echo was not the same // SMALLINT owWriteByte(int portnum, SMALLINT sendbyte) { return (owTouchByte(portnum,sendbyte) == (0xff & sendbyte)) ? TRUE : FALSE; } //-------------------------------------------------------------------------- // Send 8 bits of read communication to the 1-Wire Net and and return the // result 8 bits read from the 1-Wire Net. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: 8 bits read from 1-Wire Net // SMALLINT owReadByte(int portnum) { return owTouchByte(portnum,(SMALLINT)0xFF); } //-------------------------------------------------------------------------- // Send 8 bits of communication to the 1-Wire Net and return the // result 8 bits read from the 1-Wire Net. The parameter 'sendbyte' // least significant 8 bits are used and the least significant 8 bits // of the result is the return byte. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'sendbyte' - 8 bits to send (least significant byte) // // Returns: 8 bits read from sendbyte // SMALLINT owTouchByte(int portnum, SMALLINT sendbyte) { uchar readbuffer[10],sendpacket[10]; uchar sendlen=0; // make sure normal level owLevel(portnum,MODE_NORMAL); // check if correct mode if (UMode[portnum] != MODSEL_DATA) { UMode[portnum] = 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 ==(SMALLINT)MODE_COMMAND) sendpacket[sendlen++] = (uchar)sendbyte; // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum,sendlen,sendpacket)) { // read back the 1 byte response if (ReadCOM(portnum,1,readbuffer) == 1) { // return the response return (int)readbuffer[0]; } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); // an error occured so re-sync with DS2480 DS2480Detect(portnum); return 0; } //-------------------------------------------------------------------------- // Set the 1-Wire Net communucation speed. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'new_speed' - new speed defined as // MODE_NORMAL 0x00 // MODE_OVERDRIVE 0x01 // // Returns: current 1-Wire Net speed // SMALLINT owSpeed(int portnum, SMALLINT new_speed) { uchar sendpacket[5]; uchar sendlen=0; uchar rt = FALSE; // check if change from current mode if (((new_speed == MODE_OVERDRIVE) && (USpeed[portnum] != SPEEDSEL_OD)) || ((new_speed == MODE_NORMAL) && (USpeed[portnum] != SPEEDSEL_FLEX))) { if (new_speed == MODE_OVERDRIVE) { // if overdrive then switch to 115200 baud if (DS2480ChangeBaud(portnum,PARMSET_115200) == PARMSET_115200) { USpeed[portnum] = SPEEDSEL_OD; rt = TRUE; } } else if (new_speed == MODE_NORMAL) { // else normal so set to 9600 baud if (DS2480ChangeBaud(portnum,PARMSET_9600) == PARMSET_9600) { USpeed[portnum] = SPEEDSEL_FLEX; rt = TRUE; } } // if baud rate is set correctly then change DS2480 speed if (rt) { // check if correct mode if (UMode[portnum] != MODSEL_COMMAND) { UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; } // proceed to set the DS2480 communication speed sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_SEARCHOFF | USpeed[portnum]; // send the packet if (!WriteCOM(portnum,sendlen,sendpacket)) { OWERROR(OWERROR_WRITECOM_FAILED); rt = FALSE; // lost communication with DS2480 then reset DS2480Detect(portnum); } } } // return the current speed return (USpeed[portnum] == SPEEDSEL_OD) ? MODE_OVERDRIVE : MODE_NORMAL; } //-------------------------------------------------------------------------- // Set the 1-Wire Net line level. The values for new_level are // as follows: // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'new_level' - new level defined as // MODE_NORMAL 0x00 // MODE_STRONG5 0x02 // MODE_PROGRAM 0x04 // MODE_BREAK 0x08 (not supported) // // Returns: current 1-Wire Net level // SMALLINT owLevel(int portnum, SMALLINT new_level) { uchar sendpacket[10],readbuffer[10]; uchar sendlen=0; uchar rt=FALSE; // check if need to change level if (new_level != ULevel[portnum]) { // check if just putting back to normal if (new_level == MODE_NORMAL) { // check if correct mode if (UMode[portnum] != MODSEL_COMMAND) { UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; } // stop pulse command sendpacket[sendlen++] = MODE_STOP_PULSE; // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum,sendlen,sendpacket)) { msDelay(4); // read back the 1 byte response if (ReadCOM(portnum,1,readbuffer) == 1) { // check response byte if ((readbuffer[0] & 0xE0) == 0xE0) { rt = TRUE; ULevel[portnum] = MODE_NORMAL; } } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); } // set new level else { // check if correct mode if (UMode[portnum] != MODSEL_COMMAND) { UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; } // strong 5 volts if (new_level == 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 (new_level == MODE_PROGRAM) { // check if programming voltage available if (!ProgramAvailable[portnum]) 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(portnum); // send the packet if (WriteCOM(portnum,sendlen,sendpacket)) { // read back the 1 byte response from setting time limit if (ReadCOM(portnum,1,readbuffer) == 1) { // check response byte if ((readbuffer[0] & 0x81) == 0) { ULevel[portnum] = new_level; rt = TRUE; } } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); } // if lost communication with DS2480 then reset if (rt != TRUE) DS2480Detect(portnum); } // return the current level return ULevel[portnum]; } //-------------------------------------------------------------------------- // This procedure creates a fixed 480 microseconds 12 volt pulse // on the 1-Wire Net for programming EPROM iButtons. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE successful // FALSE program voltage not available // SMALLINT owProgramPulse(int portnum) { uchar sendpacket[10],readbuffer[10]; uchar sendlen=0; // check if programming voltage available if (!ProgramAvailable[portnum]) return FALSE; // make sure normal level owLevel(portnum,MODE_NORMAL); // check if correct mode if (UMode[portnum] != MODSEL_COMMAND) { UMode[portnum] = 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(portnum); // send the packet if (WriteCOM(portnum,sendlen,sendpacket)) { // read back the 2 byte response if (ReadCOM(portnum,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; } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); // an error occured so re-sync with DS2480 DS2480Detect(portnum); return FALSE; } //-------------------------------------------------------------------------- // Send 8 bits of communication to the 1-Wire Net and verify that the // 8 bits read from the 1-Wire Net is the same (write operation). // The parameter 'sendbyte' least significant 8 bits are used. After the // 8 bits are sent change the level of the 1-Wire net. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'sendbyte' - 8 bits to send (least significant bit) // // Returns: TRUE: bytes written and echo was the same, strong pullup now on // FALSE: echo was not the same // SMALLINT owWriteBytePower(int portnum, SMALLINT sendbyte) { uchar sendpacket[10],readbuffer[10]; uchar sendlen=0; uchar rt=FALSE; uchar i, temp_byte; // check if correct mode if (UMode[portnum] != MODSEL_COMMAND) { UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; } // set the SPUD time value sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite; // construct the stream to include 8 bit commands with the last one // enabling the strong-pullup temp_byte = sendbyte; for (i = 0; i < 8; i++) { sendpacket[sendlen++] = ((temp_byte & 0x01) ? BITPOL_ONE : BITPOL_ZERO) | CMD_COMM | FUNCTSEL_BIT | USpeed[portnum] | ((i == 7) ? PRIME5V_TRUE : PRIME5V_FALSE); temp_byte >>= 1; } // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum,sendlen,sendpacket)) { // read back the 9 byte response from setting time limit if (ReadCOM(portnum,9,readbuffer) == 9) { // check response if ((readbuffer[0] & 0x81) == 0) { // indicate the port is now at power delivery ULevel[portnum] = MODE_STRONG5; // reconstruct the echo byte temp_byte = 0; for (i = 0; i < 8; i++) { temp_byte >>= 1; temp_byte |= (readbuffer[i + 1] & 0x01) ? 0x80 : 0; } if (temp_byte == sendbyte) rt = TRUE; } } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); // if lost communication with DS2480 then reset if (rt != TRUE) DS2480Detect(portnum); return rt; } //-------------------------------------------------------------------------- // Send 1 bit of communication to the 1-Wire Net and verify that the // response matches the 'applyPowerResponse' bit and apply power delivery // to the 1-Wire net. Note that some implementations may apply the power // first and then turn it off if the response is incorrect. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'applyPowerResponse' - 1 bit response to check, if correct then start // power delivery // // Returns: TRUE: bit written and response correct, strong pullup now on // FALSE: response incorrect // SMALLINT owReadBitPower(int portnum, SMALLINT applyPowerResponse) { uchar sendpacket[3],readbuffer[3]; uchar sendlen=0; uchar rt=FALSE; // check if correct mode if (UMode[portnum] != MODSEL_COMMAND) { UMode[portnum] = MODSEL_COMMAND; sendpacket[sendlen++] = MODE_COMMAND; } // set the SPUD time value sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite; // enabling the strong-pullup after bit sendpacket[sendlen++] = BITPOL_ONE | CMD_COMM | FUNCTSEL_BIT | USpeed[portnum] | PRIME5V_TRUE; // flush the buffers FlushCOM(portnum); // send the packet if (WriteCOM(portnum,sendlen,sendpacket)) { // read back the 2 byte response from setting time limit if (ReadCOM(portnum,2,readbuffer) == 2) { // check response to duration set if ((readbuffer[0] & 0x81) == 0) { // indicate the port is now at power delivery ULevel[portnum] = MODE_STRONG5; // check the response bit if ((readbuffer[1] & 0x01) == applyPowerResponse) rt = TRUE; else owLevel(portnum,MODE_NORMAL); return rt; } } else OWERROR(OWERROR_READCOM_FAILED); } else OWERROR(OWERROR_WRITECOM_FAILED); // if lost communication with DS2480 then reset if (rt != TRUE) DS2480Detect(portnum); return rt; } //-------------------------------------------------------------------------- // This procedure indicates whether the adapter can deliver power. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE because all userial adapters have over drive. // SMALLINT owHasPowerDelivery(int portnum) { return TRUE; } //-------------------------------------------------------------------------- // This procedure indicates wether the adapter can deliver power. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE because all userial adapters have over drive. // SMALLINT owHasOverDrive(int portnum) { return TRUE; } //-------------------------------------------------------------------------- // This procedure creates a fixed 480 microseconds 12 volt pulse // on the 1-Wire Net for programming EPROM iButtons. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // // Returns: TRUE program volatage available // FALSE program voltage not available SMALLINT owHasProgramPulse(int portnum) { return ProgramAvailable[portnum]; } digitemp-3.6.0+dfsg1/userial/ds9097u/owsesu.c0000644000175000017500000000657310632073746017332 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // owSesU.C - Acquire and release a Session on the 1-Wire Net. // // Version: 2.01 // // History: 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for // multiple ports. // 2.00 -> 2.01 Added error handling. Added circular-include check. // 2.01 -> 2.10 Added raw memory error handling and SMALLINT // 2.10 -> 3.00 Added memory bank functionality // Added file I/O operations // #include "ownet.h" // external functions defined in system specific link file extern SMALLINT OpenCOM(int,char *); extern void CloseCOM(int); // external functions defined in ds248ut.c extern SMALLINT DS2480Detect(int); // exportable functions defined in owsesu.c SMALLINT owAcquire(int,char *); void owRelease(int); //--------------------------------------------------------------------------- // Attempt to acquire a 1-Wire net using a com port and a DS2480 based // adapter. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // 'port_zstr' - zero terminated port name. For this platform // use format COMX where X is the port number. // // Returns: TRUE - success, COM port opened // // exportable functions defined in ownetu.c SMALLINT owAcquire(int portnum, char *port_zstr) { // attempt to open the communications port if (!OpenCOM(portnum,port_zstr)) { OWERROR(OWERROR_OPENCOM_FAILED); return FALSE; } // detect DS2480 if (!DS2480Detect(portnum)) { CloseCOM(portnum); OWERROR(OWERROR_DS2480_NOT_DETECTED); return FALSE; } return TRUE; } //--------------------------------------------------------------------------- // Release the previously acquired a 1-Wire net. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to // OpenCOM to indicate the port number. // void owRelease(int portnum) { CloseCOM(portnum); } digitemp-3.6.0+dfsg1/userial/ad26.h0000644000175000017500000000306311055344467015412 0ustar ryanryan//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //--------------------------------------------------------------------------- // // ad26.h - Include file for Smart Battery Monitor demo. // // Version: 2.00 #define SBATTERY_FAM 0x26 digitemp-3.6.0+dfsg1/DS9097_Schematic.gif0000644000175000017500000001767011055610567016355 0ustar ryanryanGIF89aj"¥"" !!!200888A@@GGGQPPVVVa``oooqpp€€‰‰‰––– ŸŸ«««°¯¯¿¿¿À¿¿ÊÊÊÏÏÏØØØßßßéééïïïöööúúúûûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!þCreated with The GIMP,j"þ@‘pH,ȤrÉl:ŸÐ¨tJ­Z¯Ø¬vËíz¿à°xL.›Ïè´zÍn»ßð¸|N¯Ûïø¼~Ïïûÿ€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîµñòóôõôïøù€XüZöÆÓG° Vö[h°á;…T &dè°¢:‰R0F¤h±c9P@fäè±$8‘NP†$i²å6•L`¦d鲦5™JpƤi³gþ4H€æäé³(3¡F%j´é1¥D &eê´ª0©·`±ÕªWX[»f½"ö«YUaµR=ËÞÚ'iÛÊÝ7KݹxÝ’U»7¯ßY1Ê‹:˜+߉¿ ýEÊAçO ;½t—Á®±gÜv¹­ÖwDЃ§%a{îýÖØò×[ceþÕ‘sC<@›q–ÀlL§ÚªYAÌM(‚ƒ·‰¦‚vtß=6Ÿ…õõÖ!Æ]àZ%~_' ,a] |&#ÝE‰`Žöe”UÖãdCα߉¨iMÎøY”Z!£›P–—[g¦ÍÉ%AwyYE™rä§äf`vÀg6œh¶}xãœibÖ€vZ7›ž{æ#Ц<~é'#ì¥Çžw£’:©¢¢*„wF¨*ꪥfªã†ÃuÁ魀ʪk ña8F¯î*l'ÀF±µ«l&È‚ùE³–-+í$Ðw,­ÎN«í#Õæšm´Ön+n#ÝþŠ-¸þã¦[H¹b°«î»†¸ †¼ðֻϹá>‹¯·öö«¯¯öñKï ¼hðÁ'¬ð 7ìð×è/5öŒUñµÆo“vàñÇ ‡,òÈ$—lòÉ(wðÀÄÜðã²ÆíÖc±Ì†¬üˆÍ,kSX²f¼¬Ð΄à܈Ð9c#Ø@£ Ñ"pÁÓAÁÓDMUKý4QL 4M5ØD8ML]ÍÑHg\ÓœsÀµqC0€"`‘¶wC€€ô  áÁ Á‡«- Ûjpþ¶qKM€x‹àA…óm7€ÁÞFd^ºþPº(0Dè €¹æÙxކðƒÀßÇ#ÀòAÞÏ0ìDÈ~9éU/¿¼ÕM Ç+‘9ðÏß³ÛAƒ~è¥{@€Ü-›^¸å†'1;Þ·Kàûݰ¾$Œ|Í0_¸4õ Aºkßû8€ ´N¯c€Üw¶Øéïr­Ó@ÿ|WA Ðøxô0ó¦¼|Ëc¹ü!¡†uAÜ–Ä!H HY¸6ž/Xé3û0E&"†írb ª¨.vÑŠÓÎdÒ€Å>x gD#7—\¹W3SÍþÎÆ+Ôq¿ãƦò²¡Ñ wÄc/Êø¬1Ρˆ,@V“È<`‰\¼¨¸ë9€{ÂÐÁ(RtÑ"ö8ãt Êù€Ê&õyìiã"ý0ð> À¨Ó¤žw=O‚ò (À&°(ØfÈ$B&d:³™‹œÂ&°ýC”æ²C~DЀ!6{R„|ÈÜO¥›]Ò89ô Ÿüe:ð¡$³ J¢Òdà @ •D`$IB™p”] ©´lzˆ=g8€Èë³ €ÒùÎßA•œ"JÒ’šô¤(M©JWþúò°ô¥0©LgJÓš¾4 6Í©IqªÓžúô¤Óùf¼É% ¡þLº¹* ¡…‚Œ„ºÔ7¾1ŽVÍj§ˆQ‰~sRX¼Èp£º|Bë@PÏ ñCŠù‹ ¨& ¸k!è)©Ž9Á¨B`jDƒÙÔU Ì|‚Ǩ”™‘Å>Å’ pæ&9b ‘p逪Ù—JDœ¶¾ux˜+0ìʆ¼& “`¹%EÀ:̬ˆ V*,6T^Hš'(šÐÄVö«BÑE• 8Š@qD­Ý´ÚAµuÕë\ë ÀFçF¢Ò$ þXéè3šw å@FV½*=Ž­Þç{]ºú‚µkàn'”„L}wUþ4ª‘†Pƒ¦·q…' Skß^àW úå@©´ž ¡¨0< ãA½—H°uË â/`÷¾Ú5C„ÙbK”XºRdðjS\†¯£Å•x±hé[‡;˜Æd°ñEÌc2è˜ >æÅƒñ äsÈäbch¶„+Ç1ááÈ+,ò’¼‹%£AÈéx2!"Fcý L÷‰–—¨e9pY^Þn“Í!æ y®–ÉÐpÈl‡5OrÁwxs.â¬â9d&C‰žó,$cÍÁÏˤ¯ h\ºÆ†&GíÜþ>+mÑ eÃ¤Ç èúθµ™Ǧ-\žqEÊ@ò4F-ß6ǡҷ¸tS-ŽU»úÕÂK³µdýh[ƒÖTÀµ-t=0£Ã×ßš2Ï‚3í>û È6Â4Émnw³Ûàž@|_Ál18ÛɈ†¢£!Cì|µ[Í×öB¶‹€JªÚûÞ‰šE¹Ãpn:§»VÄ;s²¨ýë7Ì{Þ"@x‡:Þ†;üC p¸Ã Ãbß`è÷¡;=æu3šÝÂ1\ãMÅë~ˆÆ¨´8¹yÝk:%4‹2´€e`_™ä\P86Јc¦Á®¸¾YΗ«šÈ1Æ9¦S€ | ¡&BÊM‘FþZýêXo$Q£Ð€¬{=ë:Ï…È'qðRÇç j½µ;õR ßpꦛ¸Û½·½F:‰ÍŠ[JŒ*BgT.ŠlàðˆG|½)zÄ;~ãv‚áøªg&”ß@rðޱK¢ìJ/C½Ñ«Ÿ¥j;ò«€MB·.zÌ$´éGØEÎ Ð'ho“œR“ëÔ,*³aøÅ`ù´Éžó'Ñ»‘ùÞ¦== |"P€Ä—ú$JPÌ 427ÕL䬥E†‘HJ$ùÛÐè/À;·(‚ºÈB¨ÇÇg5…æ}G"µzŸL‰4wÐHÖAWð˜H þ€pÏ· B¡U‚`{{‡{«‡¥Þwò`}(ir*‡g$‹t(Š't"T,xxÈ0^npÑdy¬—q˜‘XÑ!Ú6{LÐMUgÁTE¨%Á¤Py‡ÂMxB¸ Pˆx#‡G}¡°F+x¡—agL‡z€‡…P JF‚3&þ4LßD4jò‚è^Ÿƒ¤—&ß”ì7|DTÀÇ?xXC°(;ø-ÅÁtH8*t5Lâ4‚cETTxTNÜÄL•h‰&èT @ù’g[†jô£§O'ºç pëWuà$À$¯þÔ`æá†‰¤( `‹0IE\ˆf€®ÑaLJa°víå|Eà^J {#{Dp p‹ÿUˆ×X¸„H…]WQ"@O ¸…¤Šfs0ãyV€Ë÷É\GÀŒÆ¤HÚX€+hWÊh‚ºƒØÁ‡ ƒsy 0†¥§]‹b\] |.HÁ„RÀsçÁÖx#ÃDXC°„O…‡GXÜŽYLô´@xœð…aÂ#Š&ÁŽUàŽ’ö0BK`Œò˜‰Ttµ“%HMs8ŽÄGIÅéAqùX|Ès yíWq9 Pe†W@G°(D7Ž(|Æu‘Cþû´uãqW›¨‘¨¡‰ IXOuÄ2;1òn| “b€"€v;˜¡Á–I0ˆ´2)â—@T§{Ñ·‹/¨uÊè}+ØHH¢Œðwh€ƒH{^ {Д}%ÖQ}c}Âø~éX…2€Ü¤uxÇ”©É€){È,n¹?#&'—{@—a`—eø·‘jMètð•9Å)ާÉéXÂéxÞAWM˜“c€Ty•˜AŒT0ˆÒÉ uG†Ç„N—x7bxéxã(žö[“÷‘wiœTy *I›—7—¦hGmŠOðƒÇ¨ °Az­2ò—ôh@¼çoQPþ›,9ŸSŸ¹yŸíØñ¨ ¡¡™Ú¶Yà(ùŒœ‰n úoŽq›ªºyllP“ê·›¡ð”ý©€H ˜±¢G ƒºÿ&p#&`x{ˆW %Œ_—u’’ ·ÏïÙ˜‰¡“DQ.Ú2³ÙiIã6“Tp¢Ø¶‹bwvg—z@ÊZL·G‘s÷rµ¡1ÙZ™‡x0s*œ§@™PЛÉv O€•nº \*o2¦o=8‘=—~hLÚ¤F£|3 §d l©€öT˜š©šº©šTPºõV%œ:ª›zbJ ZêƒZr6¥©`wmþu«÷†|ߪ~¤ïhj²P¬ pÁ¬Y ÅêpÚ¬w¬Ð «Œ°ª9W¨(†jø@­&s]¨ª’:§Š”J ÷F—w馣—ŸÃ«‘ê«Õš_ÎJ¥Wpß‚®‡ ­[ð­óèªnpJHh`£HpŽzT‹ØÑãz™ñú¡®¬æ#;Sy€¯_Ôªx€T°E ‡H0”CVN`$9`©° kåÚy{1ÅB¢hfFÝ*újáºà°2§´HiˆÚá¯s‰<HµŒX" [ˆ˜z›!´œÑ´ãˆ©f¸°-—²Á3öšhþABÐêQA¶tp³jPu€^ɱ¬§qÄÚ‡"V‘5!U—8`B¬ Q}nÛ¶~{£XK+›|UŠ/¡è#²­³6³¾„±x° q{";k$ÈÑ‹'"|`¹"»OÃø‚Ì”Q’³*8Ñ1 Ì”³E躄k­‘¸Šû’z¦ ¡&+†ÔZÛL à±Ň?«Œaº {öèºý©&Fò¼mJ"j–1"½»ðz­!ª1¶É  úqÊ®uÙ»t°F»œû ¼8¼¶È“Èû‚)b}Â7POÅLÖA²×Ñ~@…hQ€zV[t…{  (þ¢=ºgÎòµY&¶íÚcüÊ`ù€j~àE¼|~à§HÕô¹\¹ašA<ç¶ÇÛš’ÂÛuÄ*¼‡›«¤hÀXJ&h¦ÀlÆÀã+¹w@ÿ´*PLMHœéQ‹§òO¤wYL–‚ÿžA¼Ãw¹ÄM¼+¬-ì OsAÅcÒG;4ügâ»›äK ]§¤Z0ÅYPÅÝðÅ÷ ¹ †Ã–pxe€ÆX Æò*¨na»ÔÌj>:¢º\ü¼Ð[ÆÇvÊÎ\ÿ,Mí ØŠïái¸)Ω̪ҼÝ;pÖLÐVPч¬½´rÕ†Î*^=iœÅ¤y0 ÆL09ÜÚÓ<0æÏ<¹!ÝeÛLÀ+Ÿ ‡Àô*oÕ§·ÅdzÇ…}PiG þà:C@APD;ö—dAÞ:ÆpVÔ•iÖË “üÈ®ŒÎÝr|\R:Õ r’Vm7Ü#ÐC=Ý‹C8cϹ†ÖÚfØÉàkbÖn ŠÇfqQM‘˜(N"°MµÖZ-9z£ÇL ß3:R (à5Ú¤]Ú¦}Ú¨Úª}QxjÙ;»VmûrÐæ^å†n«$ˆ5ÙfÙšå™-`oìp9·Ãu«½ÜÌÝܧ­¦…íÇíÑÛÛF®<ê™&˜ºÝ~ B‘ÜQC]" PÜM09•ã×êÝ(GÝB¡°·¬}XùJ+s’àeOw}Àþ5O3?{ýÕN`6[Úñ óÈ P²#ÒÚmr[f½‡SGZœÊ±à³ŒØWtÊœüÑîàáÈ âO!âƒLâí`âí¬ÒxÌâ[.¾s(n ]<ãü×QãKÐà¦¬É Íáð}ãwiäÄãõ<ä#ÞáFäa¤âÑlÏïàãшäàä¥(ã¼kVnÔX~R~Ï\®_~Ö0® »{Š4þäa ZÞ@eŽŸ^îæiž kNçm.Ý,6 #áųjb½ y¡uÎç“á @Tã7"[—&N)¦Ññ(Vb½yÙ9£ÐRýÍL°PBÀ÷“ì$0ØOþà¨64«àvŽß%°†E"‘ùTˆ IàÕu´ÕTJ‚w·íéÞg €Ô$™ÿ · …ÉUMtµM›øÛO0@ÞBíwS9ªîäŠ>|ÅŠ$²¢dœ¸NTæûtöÅ"L¥TùäMÃn3êìáïÉ%:]à<~ÓÓí{,ç îøÀ7PÂGqÜT%£;[´ÕîºíTþÜïü^‹µñ‹ç+IÅ™%KˆùL+zGôCð«n$ô MôTHï¢M²÷ë¤拜M!é‰û—p6“ˆHð[ÆÐìãL‰åH•=|™p£…:þƒöNP9ÄönæÐðfõÔ°ôëã4·#Òù…9¬X<·òùÐ ÇwÙx£y5Ú6í^½áIÀÚS@ïÝö1T4MW¬ûÛÝ`5MP2ÝúÇ?!€‡§„mmòd ÏŸàÑ_5;ý¾ã>ô¿¯ýÔPý–k˜Ùþ  þ’ïý~pþèï êŸíì/³ï ñßû—ïöõß ÷þû¾\þ@ ‰Eã™>”Mç•N©Uë›Õn¹]ï7Ë#ÅãcÙ|­lÒct—Ïéuû¯}·÷ü¼sí¯i#£Ð0£áððC°Ññ2Rr’Œ®/íÒ1Rä@à4TTà‚Óô5U55¬ÕÕt“Ò³àÀö×ö³tµ×÷8ëÕ‹¸¯CQ9#¢bY‘ñÎ3ÃÉ“W;[{ûÔ˜Ëû¯b”¼\Ükºš”»ÝýÞo]9!77´ÿ¶O½‰µx 4˜„Þ°: ã\u-@%V´x1C+7RJ @W‚hP ÈcJ•+'q¤âòå¤q¤:ŒÄþ$Yöôù3Î(B‡Jª)ÀŸˆ ˜„¤ O S©V­Bô Ö¬’"|b#¢ƒ'‘$îDimZµD´6ië6’CˆÌ|{ê©kùöíy·’¥HŒ\´ÃÓ’ë úuüø à3 !Íl ÖfÃòÙ thn’.ýèhR#]Ï ê\ä³_‡l°Íf¶Û¢y÷¾cš-eG¬i{Fìè5‘Ø"*$€] ÀL/0Áwví˜w$Wõ‘£ÀוÚzȃ·|8à”ú…ëÛé×ßB~‰pA„7—fj^šÅNºlºæˆ ®J¡îìì{B)ðSJ¿bËb-¶fŽ]¶R;ví$Ó_¥Õ.Xy(‘e’g{–ÛЪåŽl%Ñ6þÚnÍ}ì[3†}B\²;^ÑÒu#–>Ý0Þ|ÑtÖ&ø÷ß" à‚Xˆ‚®«¸\ÀÞš-âƒÄ*3‚,ÈuUߎ}š ÙˆKÙd$°]ÀÄ ˜X„U–®šçÄ‹ÕD=Þ-¿ &eR8脚h%°“؆8æˆàƒ§©^à:¬›‘î‚øê{Ï»T¹ry>#Ÿyˆ¡…>n£6ÛX F&HÀåšLLqo./°{ð.¨Y¾ `¢D˜Í"»J³ÑžÜ µ»Ú`£5o‰Ì.BÜ ¸|à™+¨‰M_ fæh¶þ)cù6˜àæòÞ¥÷´ùÖ ¤7/ºèÍßþœá!2p0æ dvZfÕÙ¨¹õèh`,"ß‹bãܵ¯ÈòpØ–[aßãžä!dÙà€DOqñ œOþ¯Yo®úk‹ ùpüñÛ·ÿ?Ý»OïPF<áqŽsâ3_q¸´žR OKCbCls€õt}_›^צӥNÔnk¸ÍG¸-ž¬‡¿2¼òlaBCèÄö…ÈnR·ÇPØCVìÎZ2©¡7…@‰ÐaJ‘9>±@×µ†È‰uA‹kóš*#6§9- `´Ã³XÆ0HQ]õ:BŠ(˜™þÑŒqü… Ï®†uu`Äc¥*†:°àñQr$*è¨;kžP^– “˜D €‘/Ûâ )iE4Òë$Úß"SÄ:¥D q‹œZ@2V•§ ä$©h¾99ou­K^s•ÆTÞ²…¼Â)“ ‹šUÍy×£]s€‰¾R\¬_¸Tæo.²VV‰eL‘û\Ɔ»}d}Ô“ÔËoz“`ß4™8ÛöÍr‚S†ä §9 x´,O ðtg¼tÙ‘Lêf‡«_b*O|ê“9þde7I<ßô…“g …†Ž/žùªçUÔè ^^Ä…-`êÂ’¡“hãL:ɗΡ±3þ¤éüèIAÚR—ŽT¤$eÔDcrÏU\Ô"_Ò8Š@Ÿ|)ýéðÈSð%ôsnÛ(Q'C_Ñt 8¥[)!ÕƒxT&5*Q³ZÒsŠTnÔ\QKºU¯&u¨F«ÛÊ©fþ¬¢½°ªA<ŠÔ­jt¨'§YljÒòÝÕ«ð$§R‹À¾š³­|ñÚbEк8¬H‹Ýfz¦ (@5‚eàŠÚTs-H]ó X¶•¯hë_Ëظ©5¨±e*RA3 À¶`@àœ$À¶s™Œà @³P0.ûÙgÊuQ ì¨BÅŠZ×.¬ME¨]{ú6¶ö€þ‰í‹F²€°#IÉ@aT xÀÈ*8 8WˆsŒnV÷zÎu²T¬_eijMªPvø¬Eé‚ÁÙÕÚ•7ä%‚ªDÞ!H¸ ÑÀ \(P€À¯$ÚEÈerA¼_H1}0Ìœ{$ÆÂBh1e¥°a ŒØ P‰íÈAò‰\d#ïq8ò’™Üä&‹–r+î‚”µƒa‡\`…‰11Û«Üåvx¾Qà@$ÀTa¶UóšÙÜf7¿Îq–óœé\g;«y²'Ös$ì1Ì%Ó;/ÐÁv‚€YïÒJrÐñŒ—d5_ ªâŠô¦w–é¢pÔô|«C]êiy P6õªu·Êd²Ö3õåb]ëE¡z+¶Öµ’píUïØ™µ÷‚]l` {€ÆV6µ½Âe?[^Í®#´©½/‚üºÚÙv¶ ©mo÷¬já÷¸É]nsŸÝéVw¸¹ýmwÏa÷¼é]o{ßßùÖ÷¾ù-o¾àøÀ ^pƒá WøÂÞp‡?â—øÄ)^q‹_ã×øÆ9Þqä!ùÈI^r“Ÿå)WùÊYÞr—¿æ1—ùÌi^s›ßç9×ù΋;digitemp-3.6.0+dfsg1/CREDITS0000644000175000017500000000116710632073746014063 0ustar ryanryanBrian C. Lane Original DigiTemp code, and editor of submitted patches Erik Rigtorp Developed the ds9097 code for the owpd kit. Jesus Roncero Debian package maintainer Hub search fixes Manpage Eric Wilde DS2438 Humidity support Sven Geggus -n0 infinite loop Ewan Leith AIX Support Roland Roberts DS1822 and DS18B20 changes Ted Frohling 1-wire hub loan John Stoffel Solaris, AIX, FreeBSD patches Erik Rigtorp userial driver for passive DS9097 adapter Kevin Pedigo Makefile cleanup Peter Enderborg sleep change MÃ¥ns Nilsson OpenBSD (need to add more names here) digitemp-3.6.0+dfsg1/Makefile0000644000175000017500000001056011055615174014475 0ustar ryanryan# # Makefile for DigiTemp # # Copyright 1996-2005 by Brian C. Lane # See COPYING for GNU Public License # # Please note that this Makefile *needs* GNU make. BSD make won't do. # # To disable Lockfile support on Linux, chenage LOCK to no # VERSION = 3.6.0 CC = gcc CFLAGS = -I./src -I./userial -O2 -Wall # -g OBJS = src/digitemp.o src/device_name.o src/ds2438.o HDRS = src/digitemp.h src/device_name.h # Common userial header/source HDRS += userial/ownet.h userial/owproto.h userial/ad26.h \ src/device_name.h src/digitemp.h OBJS += userial/crcutil.o userial/ioutil.o userial/swt1f.o \ userial/owerr.o userial/cnt1d.o userial/ad26.o # DS9097 passive adapter support source DS9097OBJS = userial/ds9097/ownet.o userial/ds9097/linuxlnk.o \ userial/ds9097/linuxses.o userial/ds9097/owtran.o \ src/ds9097.o # DS9097-U adapter support source DS9097UOBJS = userial/ds9097u/ds2480ut.o userial/ds9097u/ownetu.o \ userial/ds9097u/owllu.o userial/ds9097u/owsesu.o \ userial/ds9097u/owtrnu.o userial/ds9097u/linuxlnk.o \ src/ds9097u.o # DS2490 adapter support DS2490OBJS = userial/ds2490/ownet.o userial/ds2490/owtran.o \ userial/ds2490/usblnk.o userial/ds2490/usbses.o \ src/ds2490.o # ----------------------------------------------------------------------- # Sort out what operating system is being run and modify CFLAGS and LIBS # # If you add a new OSTYPE here please email it to me so that I can add # it to the distribution in the next release # ----------------------------------------------------------------------- SYSTYPE := $(shell uname -s) ifeq ($(SYSTYPE), Linux) CFLAGS += -DLINUX # Set LOCK to yes for serial port locking support LOCK = no endif ifneq (, $(findstring CYGWIN,$(SYSTYPE))) CFLAGS += -DCYGWIN LIBS += -static -static-libgcc endif ifeq ($(SYSTYPE), SunOS) CFLAGS += -DSOLARIS LIBS += -lposix4 endif ifeq ($(SYSTYPE), FreeBSD) CFLAGS += -DFREEBSD endif ifeq ($(SYSTYPE), OpenBSD) CFLAGS += -DOPENBSD endif # Untested, but should work. ifeq ($(SYSTYPE), NetBSD) CFLAGS += -DNETBSD endif ifeq ($(SYSTYPE), Darwin) CFLAGS += -DDARWIN endif ifeq ($(SYSTYPE), AIX) CFLAGS += -DAIX endif ifeq ($(LOCK), yes) CFLAGS += -DLOCKDEV LIBS += -llockdev endif # USB specific flags ds2490: CFLAGS += -DOWUSB ds2490: LIBS += -lusb help: @echo " SYSTYPE = $(SYSTYPE)" @echo " CFLAGS = $(CFLAGS)" @echo " LIBS = $(LIBS)" @echo "" @echo "Pick one of the following targets:" @echo -e "\tmake ds9097\t- Build version for DS9097 (passive)" @echo -e "\tmake ds9097u\t- Build version for DS9097U" @echo -e "\tmake ds2490\t- Build version for DS2490 (USB) (edit Makefile) (BROKEN)" @echo " " @echo "" @echo "Please note: You must use GNU make to compile digitemp" @echo "" all: help # Build the Linux executable ds9097: $(OBJS) $(HDRS) $(ONEWIREOBJS) $(ONEWIREHDRS) $(DS9097OBJS) $(CC) $(OBJS) $(ONEWIREOBJS) $(DS9097OBJS) -o digitemp_DS9097 $(LIBS) ds9097u: $(OBJS) $(HDRS) $(ONEWIREOBJS) $(ONEWIREHDRS) $(DS9097UOBJS) $(CC) $(OBJS) $(ONEWIREOBJS) $(DS9097UOBJS) -o digitemp_DS9097U $(LIBS) ds2490: $(OBJS) $(HDRS) $(ONEWIREOBJS) $(ONEWIREHDRS) $(DS2490OBJS) $(CC) $(OBJS) $(ONEWIREOBJS) $(DS2490OBJS) -o digitemp_DS2490 $(LIBS) # Clean up the object files and the sub-directory for distributions clean: rm -f *~ src/*~ userial/*~ userial/ds9097/*~ userial/ds9097u/*~ userial/ds2490/*~ rm -f $(OBJS) $(ONEWIREOBJS) $(DS9097OBJS) $(DS9097UOBJS) $(DS2490OBJS) rm -f core *.asc rm -f perl/*~ rrdb/*~ .digitemprc digitemp-$(VERSION)-1.spec rm -rf digitemp-$(VERSION) # Sign the binaries using gpg (www.gnupg.org) # My key is available from www.brianlane.com sign: gpg -ba digitemp_DS* echo # Install digitemp into /usr/local/bin install: digitemp install -b -o root -g bin digitemp /usr/local/bin # Build the archive of everything archive: clean cd .. && tar --exclude *.o --exclude .svn -cvzf digitemp-$(VERSION).tar.gz digitemp-$(VERSION)/* # Build the source distribution source: archive dist: ds9097 ds9097u ds2490 sign archive dist_ds9097: ds9097 sign archive cd .. && mv digitemp-$(VERSION).tar.gz digitemp-$(VERSION)-ds9097.tar.gz dist_ds9097u: ds9097u sign archive cd .. && mv digitemp-$(VERSION).tar.gz digitemp-$(VERSION)-ds9097u.tar.gz dist_ds2490: ds2490 sign archive cd .. && mv digitemp-$(VERSION).tar.gz digitemp-$(VERSION)-ds2490.tar.gz digitemp-3.6.0+dfsg1/README0000644000175000017500000004755511055345516013733 0ustar ryanryan---------------------------------------------------------------------------- DigiTemp v3.6.0 for Linux (c)1996-2008 by Brian C. Lane ============================================================================ Thank you for using DigiTemp for Linux. If you have any problems or suggestions please feel free to contact me at bcl@brianlane.com You can get the latest information by pointing your web browser at http://www.digitemp.com/ and look at the Software page for the latest release, or use the forums to talk to other DigiTemp users. There is a DigiTemp support mailing list available from https://lists.brianlane.com/mailman/listinfo/ Quick Setup ----------- DigiTemp requires very little setup in order to work. Basically there are 4 requirements: 1. Permission to access the serial port you will be using. 2. Permission to write to /var/lock if you are using Linux 3. A 1-wire serial port adapter 4. A 1-wire sensor connected to the adapter If you think you have all of these taken care of you can try the following to see if it 'Just Works': 1. Initialize the ./.digitemprc file with the following command: digitemp -s/dev/ttyS2 -i If you had my 1-wire setup (hub and sensors) you would see this: DigiTemp v3.3.0 Copyright 1996-2004 by Brian C. Lane GNU Public License v2.0 - http://www.brianlane.com Turning off all DS2409 Couplers ... Searching the 1-Wire LAN 1F404301000000E4 : DS2409 MicroLAN Coupler 1FB03001000000B5 : DS2409 MicroLAN Coupler 1F881D01000000ED : DS2409 MicroLAN Coupler 22B9B20500000049 : DS1822 Econo-Temperature Sensor 286D1D2D000000EA : DS18B20 Temperature Sensor 104C4D55000800D9 : DS1820/DS18S20/DS1920 Temperature Sensor 1092B9330008002E : DS1820/DS18S20/DS1920 Temperature Sensor 1009212E0008004B : DS1820/DS18S20/DS1920 Temperature Sensor 1067FF33000800C2 : DS1820/DS18S20/DS1920 Temperature Sensor 26E22C1500000046 : DS2438 Temperature, A/D Battery Monior ROM #0 : 22B9B20500000049 ROM #1 : 286D1D2D000000EA ROM #2 : 104C4D55000800D9 ROM #3 : 1092B9330008002E ROM #4 : 1009212E0008004B ROM #5 : 1067FF33000800C2 ROM #6 : 26E22C1500000046 Wrote .digitemprc Your network will be different, but the output should look similar, with it listing the recognized devices, their serial numbers, and ROM numbers. 4. Read all the temperatures with this command: digitemp -a Again, if you were using the same 1-wire lan as I am you would see: DigiTemp v3.3.0 Copyright 1996-2004 by Brian C. Lane GNU Public License v2.0 - http://www.brianlane.com Jan 11 08:33:41 Sensor 0 C: 22.50 F: 72.50 Jan 11 08:33:42 Sensor 1 C: 31.44 F: 88.59 Jan 11 08:33:43 Sensor 2 C: 21.56 F: 70.81 Jan 11 08:33:44 Sensor 3 C: 12.19 F: 53.94 Jan 11 08:33:46 Sensor 4 C: 21.00 F: 69.80 Jan 11 08:33:47 Sensor 5 C: 4.38 F: 39.88 Jan 11 08:33:48 Sensor 6 C: 27.53 F: 81.56 H: 23% 5. If it doesn't work, try running the initialization again. Make sure you have the right serial port and that it works, try plugging an external modem into the port and check that it works by using a terminal program such as minicom. If all else fails, email me! On older Linux kernels there was a problem with serial port support being a loadable module. With newer (v2.2.x and later) Linux kernels I have not noticed any problems with loadable modules. The problems that people usually run into are: a. Permission problems. DigiTemp will complain if you don't have +rw permission on the serial port specified so this is a pretty easy one to catch. The same goes for permission on /var/lock/ b. Wrong serial port. Make sure you know which port the adapter is plugged into. If you are using a DS2480 based adapter DigiTemp will complain when it cannot find the DS2480. c. Bad connections. Make sure your wiring is correct. This is usually only a problem with home built passive adapters. d. Bad serial port. Test the port with an external modem to make sure it really does work. e. If you are seeing a temperature reading of 85C then you probably built your own sensors and didn't connect the sensor's +5v pin to GND to enable parasite power mode (assuming that you are not using an external +5v power supply). It can also be caused by not enough read time, the DS18S20 needs about 750mS to do a temperature conversion. This time can be adjusted with the -r X argument, but the default is 1000mS which should be fine for most applications. 6. Read the rest of this document to learn how to log data to a file, how to upload include files to a remote web server, and how to setup different logfile format strings. DigiTemp Overview ----------------- DigiTemp is a command line application used for reading 1-wire sensors like the DS18S20 temperature sensor, or DS2438 battery monitor. DigiTemp supports the following devices: DS18S20 (and older DS1820) Temperature Sensor DS18B20 Temperature Sensor DS1822 Temperature Sensor DS2438 Battery monitor DS2409 1-wire coupler (used in 1-wire hubs) DS2422 Counter DS2423 Counter The output format can be customized and all settings are stored in a configuration file (.digitemprc) in the current directory. DigiTemp can repeatedly read the sensors and output to stdout and/or to a logfile. I include a variety of scripts in Perl and Python for processing the output of DigiTemp and doing various things with the data. Like logging to a Round Robin database for easy graph generation, logging to a MySQL database, or using GNU Plot to plot graphs from logfiles. Initialization -------------- Before you can read the sensors you need to initialize the list of serial numbers (each 1-wire sensor has a unique 64 bit serial number used to address it on the bus). When you add sensors to your lan you need to rerun the initialization process -- be aware that the order that they are detected in depends on their number, so when you add new sensors it may change the order of your sensors. When you specify the -i option to initialize the .digitemprc file the program will store the serial port, serial numbers of the attached sensors, the read delay time, log format type, and the log specifier string. The .digitemprc file is written into the current directory. The .digitemprc file is read before the command line arguments are read, this way the configuration can be temporarily overridden by passing arguments to the digitemp program. Digitemp needs at least the -w, -a or -t option to tell it to walk the lan, read all sensors, or read 1 sensor. This is after you have initialized the system with the -i command of course. You need to make sure you have permisson to access the serial port and under Linux the /var/lock directory. To allow access to the serial port, add the user that will be running DigiTemp to the uucp group (or whatever group owns the serial port device). To allow access to the lock directory add the same user to the lock group. Alternativly you can set-group-id the binary to the lock group so that anyone running it will only need to be added to the serial port group, not the lock group. chmod g+s digitemp chown .lock digitemp Tree Walking ------------ No acrobatics here, but if you run ./digitemp -w -s/dev/ttySx the program will show all devices on the one-wire network and traverse all couplers connected to the main LAN. The only thing it doesn't support is nested couplers (couplers connected to the branch of another coupler). The output will identify each device connected, even if it isn't a sensor that DigiTemp supports. DigiTemp v3.3.0 Copyright 1996-2003 by Brian C. Lane GNU Public License v2.0 - http://www.brianlane.com Turning off all DS2409 Couplers ... Devices on the Main LAN 1F404301000000E4 : DS2409 MicroLAN Coupler 1FB03001000000B5 : DS2409 MicroLAN Coupler 1F881D01000000ED : DS2409 MicroLAN Coupler Devices on Main Branch of Coupler : 1F404301000000E4 Devices on Aux Branch of Coupler : 1F404301000000E4 Devices on Main Branch of Coupler : 1FB03001000000B5 22B9B20500000049 : DS1822 Econo-Temperature Sensor Devices on Aux Branch of Coupler : 1FB03001000000B5 286D1D2D000000EA : DS18B20 Temperature Sensor Devices on Main Branch of Coupler : 1F881D01000000ED 104C4D55000800D9 : DS1820/DS18S20/DS1920 Temperature Sensor 1092B9330008002E : DS1820/DS18S20/DS1920 Temperature Sensor 1009212E0008004B : DS1820/DS18S20/DS1920 Temperature Sensor 1067FF33000800C2 : DS1820/DS18S20/DS1920 Temperature Sensor Devices on Aux Branch of Coupler : 1F881D01000000ED 26E22C1500000046 : DS2438 Temperature, A/D Battery Monior Temperature Logging ------------------- To log temperatures to a logfile instead of to the console you use the -l command line option. I have a cron job that runs every 30 minutes and logs the temperatures to a file called /var/log/temperature. The cron entry look like this: 0,30 * * * * /usr/local/bin/digitemp -a -l/var/log/temperature This can be added to your crontab using the crontab -e command from the user's account that you want to run digitemp from. The format of the data to be written to the logfile can be controlled in several ways. The default is to use a format specifier string that outputs a line of data like: Dec 29 20:52:29 Sensor 1 C: 1.70 F: 35.06 The -o argument is used to change this. Using -o2 or -o3 will output all the sensor readings on a single line like: 0 23.22 1.33 12.69 The first number is the elapsed time (see timing, below) and the rest are the sensor readings, separated by tabs. This makes it easy to import the data into a spreadsheet program. The data is output in Centigrade when -o2 is used and Fahrenheit when -o3 is used. The other option is to use a format specifier string. To do this you pass the string as the argument to -o, like this: -o"%b %d %H:%M:%S Sensor %s C: %.2C F: %.2F" The specifiers are the same as those used for strftime with the addition of five special ones. %s for the sensor number, %C for the temperature in Centigrade and %F for the temperature in Fahrenheit. %R outputs the sensor's serial number in HEX, and %N output the number of seconds since Epoch (this is because DigiTemp's %s masks the %s which normally does this in strftime. See the strftime manpage for the rest of the specifiers that are supported. The new counter specifier string has 2 special specifiers: %n is the number of the counter %C is the count for that counter The counter log format is specified by the -O command line argument, it is stored in the configuration file when executed with a -i command. Humidity support adds the %h specifier for humidity from 0-100%, and the format is specified by the -H command line argument. It too is saved to the configuration file when executed with a -i command. The %C and %F in the humidity specifier will display the temperature of the humidity sensor. If the -A command is passed then the humidity sensor data will be output as raw voltages from the DS2438. The format string for this is hard-coded and the output looks like this: DigiTemp v3.3.0 Copyright 1996-2003 by Brian C. Lane GNU Public License v2.0 - http://www.brianlane.com Jan 11 16:56:00 Sensor 6 VDD: 4.70 AD: 1.46 C: 27.94 In the rrdb directory you will find a collection of scripts that I use to generate the graphs at www.brianlane.com/digitemp.php, they create a RRDB database and log data to it every 5 minutes. The web server dynamically generates a graph when a page update is requested. RRDB is the Round Robin Database Tool, and it is available for free from its website at http://ee-staff.ethz.ch/~oetiker/webtools/rrdtool/ you will also find a collection of other useful scripts, written in Perl and in Python in the perl and python directories. All of these scripts will need some tweaking to work with your unique setup. Timing ------ The Read timeout is the amount of time for DigiTemp to pause after issuing a temperature conversion command before it reads the temperature (it takes the DS1820 a few milliseconds to do the conversion and make the temperature available to DigiTemp). The default value for this is 1000mS. The Read timeout can be set by issuing the following command: digitemp -r500 Set Read timeout to 500mS digitemp -i -r500 Set Read timeout to 500mS and save to .digitemprc If Read timeout is set too short the temperature will not be read correctly. The shortest I can set it with my sensors is 300mS before they fail. You may have other problems if the delay is set too short, depending on the temperature being read. I currently have mine set to 1000mS. The older DS1820 sensors would work with a read timing of about 500mS, but the new (and greatly improved IMHO) DS18S20 takes a little longer, between 750mS and 1S, so I have set the default to 1S. Repeated Temperature Sampling ----------------------------- You can setup a script to repeatedly call DigiTemp and process its output, or you can setup DigiTemp to repeatedly sample the sensors and output the data in one of the logfile formats specified in the 'Temperature Logging' section of this document. -dx This sets the sample interval. x is a number in seconds. -d5 will sample at 5 second intervals. The number of sensors that you have attached will determine the minimum interval that you can use. It can take as long as 1/2 second to sample each sensor attached, so if you have 6 sensors you will probably have a minimum sample interval of 3 seconds. The program will tell you when the sampling process has taken longer than the interval you have specified so that you can adjust it accordingly. -nx This sets the number of times to sample all the specified sensors. -n10 will sample 10 times. Setting -n0 will make it loop forever. The output can be sent to a file by using the -lfilename.txt options. So to log data every 10 seconds for 30 minutes you would run DigiTemp to sample every 10 seconds for a count of 180 (10 x 180 = 1800 seconds = 3 minutes) like this: digitemp -a -d10 -n180 -o2 -ldata1.txt This outputs the data as tab separated Centigrade readings to a file named data1.txt in the current directory. Web scripts ----------- I have written some Perl scripts for use with local or remote web pages: web_temp This can be used as a CGI binary and will show the last two entries from the /var/log/temperature file inc_temp This can be called from a cron job to create a server side include file that can be included from your webpage. rem_temp This is the script I use to update my webpage at www.brianlane.com/digitemp.php every hour (or whenever the script can get through the busy signals). It creates a shtml file in the /tmp/ directory and then uses the Perl ftp functions to upload it to the remote site. The script lists the modules that need to be added to Perl to enable ftp. You need to have a connection script working for this script to work correctly. Or if you have diald just comment out the ppp-on and off lines. Please consult the various Linux howto FAQs for information on how to construct the connect scripts if you don't already have them set up. maxplot This perl script generates the temperature graph that you can use on your webpage. They require the GD module for perl, which is available from - http://www.perl.com/CPAN-local//modules/by-module/GD/ It generates a .gif file, and move the file to the final location, so it will need some small changes in the paths and ownership at the end of the scripts to customize it for your setup. RRD tool I have also written several scripts to manipulate data with RRD (Round Robin Database) tool databases. RRD tool is available from - http://ee-staff.ethz.ch/~oetiker/webtools/rrdtool/ There are several scripts, one to add data to the database, and one to retrieve data as a .png image. NetSaint I have written a Net Saint/Nagios (http://www.nagios.com) plugin. It is named check_digitemp.pl and it located in the perl directory. Installation instructions are in the top of the file's comments. MySQL I have written a perl script to log temperature readings to a MySQL database. It is named digitemp_mysql.pl and is in the perl directory. Instructions for setup and use are in the README file in the perl directory. The scripts have been commented so that you can change them easily (I hope! Email any changes you have). There are several variables that need to be setup for your system before they will run. If you have any comments, questions, or scripts that you would like to donate, drop me an email, and I'll set up a ftp directory for user contributions. Have Fun! And when you get your sensors up on your website send me the URL and I will add it to the list at http://www.digitemp.com/users.shtml Brian C. Lane bcl@brianlane.com http://www.brianlane.com Release notes ------------- Version 3.6.0 adds ... Version 3.5.0 adds DS1923 Hygrochron support, fixes some small bugs in the userial driver. A lockdev bug was fixed (wasn't unlocking when done), a crash in free_couplers() was fixed, better error reporting when trying to access serial ports that don't exist, compiled for Windows with cygiwn. DS2490/9490 support still doesn't work well for me, although others have had success with it. Version 3.4.0 fixes temperature output using -o2 and -o3 log formats with the DS2438 sensor. Version 3.3.2 fixes the broken DS9097 support that I hosed in v3.3.1 and adds a performance patch to DS9097 from Erik Rigtorp that should speed up passive adapter operations. Version 3.3.1 works with the DS9490R USB adapter using the DS2490 USB to 1-wire adapter chip. It needs to be run as root, and your version of libusb may need to be patched using the patch in the ./contrib directory Version 3.3.0 adds support for the DS2490 USB adapter, DS2438 battery monitor and AAG TAI-8540 humidity sensor module. Additional format string specifiers have been added to handle the humidity reading. See the Initialization section below. The binary generated when building from source is now digitemp_DS9097, digitemp_DS9097U, or digitemp_DS2490 depending on which build you do. You can then make a symlink to 'digitemp' for whichever adapter you need to use. I now recommend use of the iButtonLink from www.ibuttonlink.com, it is 100% compatible with the DS9097U, but has been engineered to work with longer networks more reliably. Version 3.1.0 adds support for the DS2406 counters. A new output format specifier has been added, using the -O option (capital Oh, not lower case). I have included my first pass at a python script to log to MySQL and RRD. Version 3.0.0 adds support for both the DS9097 passive adapter, and the newer DS9097U adapter. It also introduces a better makefile and less CPU usage when repeatedly reading multiple sensors. Version 2.5 adds compilation under Solaris. A new log option of %R has been added to output the serial number in hex in the logging output string. The quiet -q option now quiets down the 1-Wire walk and initalize routine so that only the important information is output. Version 2.4 fixes the problems (finally!) with the DS18B20 and DS1822 sensors. I have also modified the search and read algorithms so that they will work faster when used with a 1-wire hub. Version 2.3 adds support for one wire hubs like Simon Atkin's hub that can be found at www.simat.enta.net Version 2.x.x removes support for the old adapter (based on the one described in App. Note 74 from Dallas Semiconductor. Version 1.3 still supports the older adapters and is now also released under the GNU public license). This new version uses the DS9097-U adapter available from Dallas Semiconductor. You can order them from their iButton webpage at www.ibutton.com This adapter is more expensive but is easier to program and support higher current capability so that it should work at higher temperatures than the previous adapter. digitemp-3.6.0+dfsg1/rrdb/0000755000175000017500000000000010632073746013767 5ustar ryanryandigitemp-3.6.0+dfsg1/rrdb/temp-all.cgi0000755000175000017500000000563310632073746016200 0ustar ryanryan#!/usr/bin/perl -w # # DigiTemp v2.1 RRDB Temperature Graph # # Copyright 1997-2001 by Brian C. Lane www.brianlane.com # 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., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA # # REQUIRES: # RRD tool binary # CGI (comes with perl5) use RRDp; use CGI; $cgi = new CGI; # Load the CGI routines # Find the RRD executable, look in the standard locations # If your rrdtool is installed someplace else, fill in the proper location # below: if ( -x "/usr/bin/rrdtool") { RRDp::start "/usr/bin/rrdtool"; } elsif ( -x "/usr/local/bin/rrdtool") { RRDp::start "/usr/local/bin/rrdtool"; } elsif ( -x "/usr/local/rrdtool/bin/rrdtool" ) { RRDp::start "/usr/local/rrdtool/bin/rrdtool"; } else { die "Could not find rrdtool binary\n"; } # The RRD database to get the data from $rrd = "/tmp/digitemp.rrd"; # Make the variables easier to use and assign defaults if not set if( !$cgi->param('starttime') ) { $starttime = "-1day"; } else { $starttime = $cgi->param('starttime'); } if( !$cgi->param('endtime') ) { $endtime = time; } else { $endtime = $cgi->param('endtime'); } if( !$cgi->param('width') ) { $width = "400"; } else { $width = $cgi->param('width'); } if( !$cgi->param('height') ) { $height = "100"; } else { $height = $cgi->param('height'); } if( !$cgi->param('label') ) { $label=""; } else { $label = $cgi->param('label'); } $var = $cgi->param('var'); # Diagnostic output #print STDERR "start = $starttime\n"; #print STDERR "end = $endtime\n"; #print STDERR "width = $width\n"; #print STDERR "height = $height\n"; #print STDERR "var = $var\n"; #print STDERR "label = $label\n"; # Output a HTML header for the PNG image to follow print $cgi->header('image/png'); # Generate the graph RRDp::cmd "graph - --imgformat PNG", "--start '$starttime' --end '$endtime'", "--width $width --height $height", "DEF:room_c=$rrd:room:AVERAGE", "DEF:attic_c=$rrd:attic:AVERAGE", "DEF:desk_c=$rrd:desk:AVERAGE", "CDEF:room_f=room_c,9,*,5,/,32,+", "CDEF:attic_f=attic_c,9,*,5,/,32,+", "CDEF:desk_f=drink_c,9,*,5,/,32,+", "LINE1:room_f#00FF00:'Computer Room'", "LINE1:attic_f#FF0000:'Attic'", "LINE1:desk_f#0000FF:'Desk'"; $answer=RRDp::read; print $$answer; RRDp::end; digitemp-3.6.0+dfsg1/rrdb/temp-minmax.cgi0000755000175000017500000000737510632073746016726 0ustar ryanryan#!/usr/bin/perl -w # # DigiTemp v2.1 RRDB Temperature Graph with Min/Max # # Copyright 1997-2001 by Brian C. Lane www.brianlane.com # 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., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA # REQUIRES: # RRD tool binary # CGI (comes with perl5) use RRDp; use CGI; $cgi = new CGI; # Load the CGI routines # Find the RRD executable, look in the standard locations # If your rrdtool is installed someplace else, fill in the proper location # below: if ( -x "/usr/bin/rrdtool") { RRDp::start "/usr/bin/rrdtool"; } elsif ( -x "/usr/local/bin/rrdtool") { RRDp::start "/usr/local/bin/rrdtool"; } elsif ( -x "/usr/local/rrdtool/bin/rrdtool" ) { RRDp::start "/usr/local/rrdtool/bin/rrdtool"; } else { die "Could not find rrdtool binary\n"; } # The RRD database to get the data from $rrd = "/tmp/digitemp.rrd"; # Make the variables easier to use and assign defaults if not set if( !$cgi->param('starttime') ) { $starttime = "-1day"; } else { $starttime = $cgi->param('starttime'); } if( !$cgi->param('endtime') ) { $endtime = time; } else { $endtime = $cgi->param('endtime'); } if( !$cgi->param('width') ) { $width = "400"; } else { $width = $cgi->param('width'); } if( !$cgi->param('height') ) { $height = "100"; } else { $height = $cgi->param('height'); } if( !$cgi->param('label') ) { $label=""; } else { $label = $cgi->param('label'); } $var = $cgi->param('var'); # Diagnostic output #print STDERR "start = $starttime\n"; #print STDERR "end = $endtime\n"; #print STDERR "width = $width\n"; #print STDERR "height = $height\n"; #print STDERR "var = $var\n"; #print STDERR "label = $label\n"; RRDp::cmd "last $rrd"; $lastupdate = RRDp::read; # Output a HTML header for the PNG image to follow print $cgi->header('image/png'); # Generate the graph RRDp::cmd "graph - --imgformat PNG", "--start '$starttime' --end '$endtime'", "--width $width --height $height", "DEF:room_c=$rrd:room:AVERAGE", "DEF:attic_c=$rrd:attic:AVERAGE", "DEF:desk__c=$rrd:desk:AVERAGE", "CDEF:room_f=room_c,9,*,5,/,32,+", "CDEF:attic_f=attic_c,9,*,5,/,32,+", "CDEF:desk_f=desk_c,9,*,5,/,32,+", "COMMENT:\" \"", "COMMENT:\" Min Max Avg Last\\n\"", "COMMENT:\" \"", "GPRINT:attic_f:MIN:\"Attic %5.2lf F\"", "GPRINT:attic_f:MAX:\" %5.2lf F\"", "GPRINT:attic_f:AVERAGE:\" %5.2lf F\"", "GPRINT:attic_f:LAST:\" %5.2lf F\\n\"", "COMMENT:\" \"", "GPRINT:room_f:MIN:\"Room %5.2lf F\"", "GPRINT:room_f:MAX:\" %5.2lf F\"", "GPRINT:room_f:AVERAGE:\" %5.2lf F\"", "GPRINT:room_f:LAST:\" %5.2lf F\\n\"", "COMMENT:\" \"", "GPRINT:desk_f:MIN:\"Desk %5.2lf F\"", "GPRINT:desk_f:MAX:\" %5.2lf F\"", "GPRINT:desk_f:AVERAGE:\" %5.2lf F\"", "GPRINT:desk_f:LAST:\" %5.2lf F\\n\"", "COMMENT:\"\\s\"", "LINE1:room_f#FF8000:'Computer Room'", "LINE1:attic_DS18S20_f#8080F0:'Attic'", "LINE2:desk_DS18S20_f#008000:'Desk\\c'", "COMMENT:\"Last Updated ". localtime($$lastupdate) . "\\c\""; $answer=RRDp::read; print $$answer; RRDp::end; digitemp-3.6.0+dfsg1/rrdb/README0000644000175000017500000000217410632073746014653 0ustar ryanryan DigiTemp v2.4 rrdb scripts Copyright 1999-2002 by Brian C. Lane www.brianlane.com All Rights Reserved The Round Robin Database is a great way to store data that you want to graph. You can get it from: http://ee-staff.ethz.ch/~oetiker/webtools/rrdtool/ log_temps calls digitemp and adds the current temperature readings to the RRD database. It should be called from a crontab at regular intervals. log-temperature.pl is a Perl script that runs digitemp and inserts the new samples into the RRDB, optionally it can create a text file for use in an email signature. make_temps creates a RRD database suitable for logging 3 sensors of data. temp-all.cgi temp-one.cgi are scripts to generate .png graphs of temperature data. Insert them into your webpage with: temp-minmax.cgi generates a graph with minimum and maximum printed on the graph. The suggested initialization sets up digitemp to output the temperature in Centigrade and the conversion to Fahrenheit. The -o option passed to digitemp when it is initalized controls how the temperature is output. digitemp-3.6.0+dfsg1/rrdb/log_temp0000755000175000017500000000277310632073746015534 0ustar ryanryan#!/bin/bash # DigiTemp RRD logging script # Copyright 1997-2002 by Brian C. Lane www.brianlane.com # 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., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA # # Call this from crontab every 5 minutes. Make sure the .digitemprc is in # your root directory or specify the configuration file using -c filename # on the digitemp command line in the reading variable below. # Get the current temperatures, digitemp has been previously initalized with # digitemp -i -s /dev/ttyS0 -o2 -a # Run it in quiet mode, output is 0\tsensor#1\tsensor#2\tsensor#3 reading=`/usr/local/bin/digitemp -a -q` # Diagnostic output room=`echo $reading | gawk '{print $2}'` attic=`echo $reading | gawk '{print $3}'` drink=`echo $reading | gawk '{print $4}'` # Update the database /usr/local/rrdtool/bin/rrdtool update /root/rrdb/digitemp.rrd N:$room:$drink:$attic digitemp-3.6.0+dfsg1/rrdb/log-temperature.pl0000755000175000017500000000525110632073746017446 0ustar ryanryan#!/usr/bin/perl -w # # DigiTemp v2.3 RRDB Temperature logger # # Copyright 1997-2002 by Brian C. Lane www.brianlane.com # 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., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA # # This require the RRDB pipe module for Perl, available with the RRDB source # from http://ee-staff.ethz.ch/~oetiker/webtools/rrdtool/ use RRDp; # Convert centigrade to fahrenheit sub ctof { ($temp_c) = @_; return 32 + (($temp_c * 9)/5); } # Find the RRD executable, look in the standard locations # If your rrdtool is installed someplace else, fill in the proper location # below: if ( -x "/usr/bin/rrdtool") { RRDp::start "/usr/bin/rrdtool"; } elsif ( -x "/usr/local/bin/rrdtool") { RRDp::start "/usr/local/bin/rrdtool"; } elsif ( -x "/usr/local/rrdtool/bin/rrdtool" ) { RRDp::start "/usr/local/rrdtool/bin/rrdtool"; } else { die "Could not find rrdtool binary\n"; } # The RRD database to put the data into $wx_rrd = "/tmp/digitemp.rrd"; # Read the output from digitemp # Output in form 0\troom\tattic\tdrink open( DIGITEMP, "digitemp -a -q -o2 |" ); while( ) { # print "$_\n"; chomp; if( $_ =~ /^nanosleep/i ) { $now = localtime; open( ERRLOG, ">>/tmp/dt-error") or die "Error opening dt-error"; print ERRLOG "nanosleep error at $now\n"; close( ERRLOG ); die "nanosleep error"; } else { ($null,$desk_DS18S20,$attic_DS18S20,$room) = split(/\t/); } } close( DIGITEMP ); # Put the info into the weather rrd database room:drink:attic RRDp::cmd "update $wx_rrd N:$room:$attic_DS18S20:$desk_DS18S20"; #$answer=RRDp::read; # This section was used to create up to date email signature files # Create the email header in Fahrenheit #open( HEADER, ">/tmp/.header") or die "Error opening .header"; #$now = localtime; #print HEADER "[$now]--[Inside "; #printf HEADER "%0.2f",ctof( $room ); #print HEADER "F]--[Outside "; #printf HEADER "%0.2f",ctof( $attic_DS18S20 ); #print HEADER"F]--[Drink "; #printf HEADER "%0.2f",ctof( $desk_DS18S20 ); #print HEADER "F]--\n"; #close( HEADER ); exit; digitemp-3.6.0+dfsg1/rrdb/make_temps0000755000175000017500000000267110632073746016050 0ustar ryanryan#!/usr/bin/perl -w # # DigiTemp v2.1 RRDB database Creation # # Copyright 1997-2001 by Brian C. Lane www.brianlane.com # 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., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA use Time::Local; use RRDp; RRDp::start "/usr/local/rrdtool/bin/rrdtool"; # Create the database RRDp::cmd "create digitemp.rrd \ DS:room:GAUGE:600:U:U \ DS:attic:GAUGE:600:U:U \ DS:desk:GAUGE:600:U:U \ RRA:AVERAGE:0.5:1:600 \ RRA:AVERAGE:0.5:6:700 \ RRA:AVERAGE:0.5:24:775 \ RRA:AVERAGE:0.5:288:797 \ RRA:MIN:0.5:1:600 \ RRA:MIN:0.5:6:700 \ RRA:MIN:0.5:24:775 \ RRA:MIN:0.5:288:797 \ RRA:MAX:0.5:1:600 \ RRA:MAX:0.5:6:700 \ RRA:MAX:0.5:24:775 \ RRA:MAX:0.5:288:797"; $answer = RRDp::read; #print $$answer; RRDp::end; digitemp-3.6.0+dfsg1/rrdb/temp-one.cgi0000755000175000017500000000550511055570613016202 0ustar ryanryan#!/usr/bin/perl -w # # DigiTemp v2.1 RRDB Temperature Graph (single sensor) # # Copyright 1997-2001 by Brian C. Lane www.brianlane.com # 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., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA # # REQUIRES: # RRD tool binary # CGI (comes with perl5) use RRDp; use CGI; $cgi = new CGI; # Load the CGI routines # Find the RRD executable, look in the standard locations # If your rrdtool is installed someplace else, fill in the proper location # below: if ( -x "/usr/bin/rrdtool") { RRDp::start "/usr/bin/rrdtool"; } elsif ( -x "/usr/local/bin/rrdtool") { RRDp::start "/usr/local/bin/rrdtool"; } elsif ( -x "/usr/local/rrdtool/bin/rrdtool" ) { RRDp::start "/usr/local/rrdtool/bin/rrdtool"; } else { die "Could not find rrdtool binary\n"; } # The RRD database to get the data from $rrd = "/tmp/digitemp.rrd"; # Make the variables easier to use and assign defaults if not set if( !$cgi->param('starttime') ) { $starttime = "-1day"; } else { $starttime = $cgi->param('starttime'); } if( !$cgi->param('endtime') ) { $endtime = time; } else { $endtime = $cgi->param('endtime'); } if( !$cgi->param('width') ) { $width = "400"; } else { $width = $cgi->param('width'); } if( !$cgi->param('height') ) { $height = "100"; } else { $height = $cgi->param('height'); } if( !$cgi->param('label') ) { $label=""; } else { $label = $cgi->param('label'); } $var = $cgi->param('var'); if( !$cgi->param('color') ) { $color = "#000000"; } else { $color = $cgi->param('color'); } # Diagnostic output #print STDERR "start = $starttime\n"; #print STDERR "end = $endtime\n"; #print STDERR "width = $width\n"; #print STDERR "height = $height\n"; #print STDERR "var = $var\n"; #print STDERR "label = $label\n"; #print STDERR "color = $color\n"; # Output a HTML header for the PNG image to follow print $cgi->header('image/png'); # Generate the graph RRDp::cmd "graph - --imgformat PNG", "--start '$starttime' --end '$endtime'", "--width $width --height $height", "DEF:temp_c=$rrd:$var:AVERAGE", "CDEF:temp_f=temp_c,9,*,5,/,32,+", "LINE1:temp_f$color:'$label'"; $answer=RRDp::read; print $$answer; RRDp::end; digitemp-3.6.0+dfsg1/perl/0000755000175000017500000000000010632073746014000 5ustar ryanryandigitemp-3.6.0+dfsg1/perl/rem_temp0000755000175000017500000001022410632073746015535 0ustar ryanryan#!/usr/bin/perl -w # # DigiTemp remote system update script # Copyright 1997-2001 by Brian C. Lane www.brianlane.com # 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., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA # # # Read the temperature logfile, write it to an include file for the webpage, # then ftp the files to the destination server. # # The following perl extensions are required : # libnet package from http://www.perl.com/CPAN-local/modules/by-module/Net/ # I used libnet-1.0506.tar.gz # # Data-Dumper package from: CPAN/modules/by-module/Data/Data-Dumper-x.x.tar.gz # I used Data-Dumper-2.07.tar.gz # # Sensor #0 is the Window # Sensor #1 is the inside of the Linux box # # Dec 18 21:46:47 Sensor 0 C: 8.81 F: 47.86 # Dec 18 21:46:47 Sensor 1 C: 26.41 F: 79.54 # use Net::FTP; # Include file for the webpage (included from the main page) $inc_file = "/tmp/temp.inc"; # Temperature logfile updated by seperate DigiTemp daemon $log_file = "/var/log/temperature"; # Script to run to bring up the link # I use diald, you probably use something different. $ip_up = "/usr/sbin/dialdc up"; # Your username for the destination ftp server $ftp_user = "username"; # Your password for the destination ftp server $ftp_pass = "password"; # Destination ftp server's address $ftp_host = "ftp.host.com"; # Directory on the destination ftp server to place $inc_file $dest_dir = "/home/login/public_html"; # Create a new include file, overwrite the old one open( INCFILE, ">$inc_file") || die "Can't open $inc_file"; # Include a break line and center the text print INCFILE "
\n"; print INCFILE "
\n"; # You should customize this! print INCFILE "The current temperatures are

\n"; # Run tail -2 /var/log/temperature and parse the output # The -2 is the number of sensors you have (last 2 lines from logfile) open( TEMPLOG, "tail -2 $log_file |") || die "Can't fork: $!"; # Parse the output of the tail program while( ) { # Get the time and date, sensor number, temperature in c and f ($month,$day,$time,$d1,$sensor,$d1,$centigrade,$d1,$fahrenheight) = split( " ", $_ ); # Print some custom messages for the sensors # The \xB0 is supposed to be a degree symbol. This works on some systems # but not on others. if( $sensor eq '0' ) { print INCFILE "The modems are at $fahrenheight\xB0 F ($centigrade\xB0 C)
\n"; } if( $sensor eq '1' ) { print INCFILE "The room is a "; if( $fahrenheight < 40.0 ) { print INCFILE "freezing"; } if( $fahrenheight >= 40.0 and $fahrenheight < 70.0 ) { print INCFILE "chilly"; } if( $fahrenheight >= 70.0 and $fahrenheight < 80.0 ) { print INCFILE "comfortable"; } if( $fahrenheight >= 80.0 and $fahrenheight < 100.0 ) { print INCFILE "balmy"; } if( $fahrenheight >= 100.0 ) { print INCFILE "blistering"; } print INCFILE " $fahrenheight\xB0 F ($centigrade\xB0 C)
\n"; } } print INCFILE "Last updated: $month $day $time
\n"; # Blantant advertisement print INCFILE "

These temperatures generated with ";
print INCFILE "";
print INCFILE "DigiTemp

\n"; print INCFILE "
\n"; close( TEMPLOG ); close( INCFILE ); # Send it to the server # Fire up the link system $ip_up; # Wait a little bit to let ppp0 come up sleep 60; # Send it to the server $ftp = Net::FTP->new($ftp_host); $ftp->login($ftp_user,$ftp_pass); $ftp->cwd($dest_dir); $ftp->binary(); $ftp->put($inc_file); $ftp->quit; # Shut down the link system $ip_down; # done! digitemp-3.6.0+dfsg1/perl/maxplot0000755000175000017500000002010510632073746015410 0ustar ryanryan#!/usr/bin/perl # -*- Perl -*- # # DigiTemp v2.1 gnuplot script # Modified by Brian C. Lane www.brianlane.com # # Modified plot script from Russell Nelson # for use with the GD module for Perl # # The GD module can be found at: # http://www.perl.com/CPAN-local//modules/by-module/GD/ # # More mods to add maximum and minimum temp display for each day # NOTE: You will need to change the commands at the bottom that tell # where to store and move the final .gif file to. # use GD; # Transform the temperature into graph coordinates. Convert to Farenheit # I already have fahrenheight data, so no conversion is needed. sub ytransform { $temp = shift; # $temp = $temp * 9 / 5 + 32; return int(250 - 2*$temp); } # You will need to customize these values for your setup $height = 350; $hmargin = 40; $middlex = 300; # display them all! $dx=2.0/1.0; # # of temperatures per sample (number of sensors) $sensors = 3; $samples_per_hour = 2; # 5 Days, 24 hours a day, 2 samples per hour $samples = 5*24* $samples_per_hour; $width = $hmargin + $samples*$dx + $hmargin; # print PLOT "create plot $width $height\n"; $im = new GD::Image( $width, $height ); # Allocate a bunch of colors ($white,$black,$red,$green,$orange,$lightgreen,$blue,$skyblue) = ( $im->colorAllocate(255, 255, 255), $im->colorAllocate(0, 0, 0), $im->colorAllocate(255, 0, 0), $im->colorAllocate(0,255,0), $im->colorAllocate(255,0,255), $im->colorAllocate(0,128,0), $im->colorAllocate(0,0,255), $im->colorAllocate(100,100,255) ); # Grayscale -- Not currently used. I'll skip for now #for ($i=0; $i<128; $i++) { # print PLOT "colorallocate plot gray$i ".$i*2 ." ".$i*2 ." ".$i*2 ."\n"; #} #sub dogray { # ($light) = @_; # # if ($light < -70) { # $gray = int(0.5 + 32 * ($light - -92) / (-70 - -92)); # } elsif ($light < 265) { # $gray = int(32.5 + 32 * ($light - -70) / (265 - -70)); # } else { # $gray = int(64.5 + 64 * ($light - 265) / (290 - 265)); # } # $gray = 0 if ($gray < 0); # $gray = 127 if ($gray > 127); # print PLOT "filledrectangle plot "; # print PLOT "$x 20 "; # print PLOT $x+$dx." ".($height-20)." gray$gray\n"; #} # Draw a Horizontal line at a temperature point sub hline { ($y,$color) = @_; $color = $skyblue unless $color; $yname = $y; $y = &ytransform($y); $ychar = $y-6; $numleft = 10; $lineleft = 26; $lineright = $width - 24; $numright = $width - 20; # print PLOT "string plot gdFont6x13 $numleft $ychar \"$yname\" $color\n"; $im->string(gdSmallFont,$numleft,$ychar,$yname,$color); # print PLOT "line plot $lineleft $y $lineright $y $color\n"; $im->line($lineleft,$y,$lineright,$y,$color); # print PLOT "string plot gdFont6x13 $numright $ychar \"$yname\" $color\n"; $im->string(gdSmallFont,$numright,$ychar,$yname,$color); } # Draw the temperature reference lines #&hline(-20); &hline(0 ); &hline(20 ); &hline(32, $lightgreen ); &hline(40 ); &hline(60 ); &hline(80 ); &hline(100 ); sub xtransform { return $hmargin + $dx * shift; } # Draw a vertical line sub vline { ($x,$label,$color) = @_; $color = $skyblue unless $color; $x = &xtransform($x); $linetop = &ytransform(100); $linebot = &ytransform(-20); $ychar = &ytransform(107); # print PLOT "string plot gdFont6x13 $x $ychar \"$label\" $color\n"; $im->string(gdSmallFont,$x-5,$ychar,$label,$color); # print PLOT "line plot $x $linetop $x $linebot $color\n"; $im->line($x,$linetop,$x,$linebot,$color); } # See if the min or max data for the current day should be changed # This function has been tested and works sub minmax { ($sample,$temp,$sensor) = @_; $day = int($sample / (24 * $samples_per_hour ) ); if( $temp > $max_temp[$day][$sensor] ) { #print "oldmax[$day][$sensor] = $max_temp[$day][$sensor]\n"; $max_temp[$day][$sensor] = $temp; #print "newmax[$day][$sensor] = $max_temp[$day][$sensor]\n"; } if( $temp < $min_temp[$day][$sensor] ) { #print "oldmin[$day][$sensor] = $min_temp[$day][$sensor]\n"; $min_temp[$day][$sensor] = $temp; #print "newmin[$day][$sensor] = $min_temp[$day][$sensor]\n"; } } # --------------------------------[ MAIN CODE ]---------------------------- # Draw the vertical day lines &vline(0*24*$samples_per_hour," -5d"); &vline(1*24*$samples_per_hour," -4d"); &vline(2*24*$samples_per_hour," -3d"); &vline(3*24*$samples_per_hour," -2d"); &vline(4*24*$samples_per_hour," yesterday"); &vline(5*24*$samples_per_hour," now"); # Here we read in all the samples. I have 3 temps for every # 30 minutes within the day. $lines = $sensors * $samples; open(DOTTEMP, "tail -$lines /gonzo/var/log/temperatures|"); @dottemp = ; close(DOTTEMP); # Now all the temps are in dottemp -- it might be better to read it line # by line for bigger files? # Initalize the initial variables - I should use a list for this $x = $hmargin; $_= $dottemp[0]; @_ = split( " ", $_ ); $lasty0 = &ytransform($_[8]); $_= $dottemp[1]; @_ = split( " ", $_ ); $lasty1 = &ytransform($_[8]); $_= $dottemp[2]; @_ = split( " ", $_ ); $lasty2 = &ytransform($_[8]); # Init the max and min temps and their points on the graph # Keep track of data for all of the last 5 days for( 0 .. 4 ) { $day = $_; for( 0 .. 2 ) { $max_temp[$day][$_] = -50; $min_temp[$day][$_] = 200; } } $sample = 0; # Plot each of the datapoints. foreach (@dottemp) { # Get the time and date, sensor number, temperature in c and f ($month,$day,$time,$d1,$sensor,$d1,$centigrade,$d1,$fahrenheight) = split(" ", $_ ); # Plot the next line for each sensor # 0 - Harddrive #1 in gonzo # 2 - Room Temperature # 1 - Outside temperature if( $sensor eq '0' ) { $color = $red; $y0 = &ytransform($fahrenheight); $im->line(int($x),$lasty0,int($x+$dx),$y0,$color); $lasty0 = $y0; # Run minmax for the current day and sensor &minmax( $sample, $fahrenheight, 0 ); } if( $sensor eq '1' ) { $color = $green; $y1 = &ytransform($fahrenheight); $im->line(int($x),$lasty1,int($x+$dx),$y1,$color); $lasty1 = $y1; # Run minmax for the current day and sensor &minmax( $sample, $fahrenheight, 1 ); } if( $sensor eq '2' ) { $color = $orange; $y2 = &ytransform($fahrenheight); $im->line(int($x),$lasty2,int($x+$dx),$y2,$color); $lasty2 = $y2; # Run minmax for the current day and sensor &minmax( $sample, $fahrenheight, 2 ); # Count the number of samples so we can figure out what day it is $sample++; # move to next position $x += $dx; } } # Print the Header for the Min/Max data for each day for( 0 .. 4 ) { $im->string(gdSmallFont,3+&xtransform($_*24*$samples_per_hour),&ytransform(-1),"Min Max",$black); } # Print the min and max temperatures # Print the min/max for each day and sensor for( 0 .. 4 ) { $im->string(gdSmallFont,3+&xtransform($_*24*$samples_per_hour),&ytransform(-6),sprintf("%-6s %s",$min_temp[$_][0],$max_temp[$_][0]),$red); $im->string(gdSmallFont,3+&xtransform($_*24*$samples_per_hour),&ytransform(-11),sprintf("%-6s %s",$min_temp[$_][1],$max_temp[$_][1]),$green); $im->string(gdSmallFont,3+&xtransform($_*24*$samples_per_hour),&ytransform(-16),sprintf("%-6s %s",$min_temp[$_][2],$max_temp[$_][2]),$orange); } # Add the Date and time $date = `date "+Generated at %H:%M on %a, %b %d %Y"`; chop $date; $im->string(gdSmallFont,$middlex-5,&ytransform(-30),$date,$black); # Advertise! $im->string(gdSmallFont,$middlex-5,&ytransform(-35),"with DigiTemp - http://www.brianlane.com",$black); # Print the Color Key $im->string(gdSmallFont,$hmargin,&ytransform(-30),"Harddrive #1",$red); $im->string(gdSmallFont,$hmargin,&ytransform(-35),"Room Temperature",$green); $im->string(gdSmallFont,$hmargin,&ytransform(-40),"Outside Temperature",$orange); # Output it to a .gif image file open( PLOT, ">/tmp/tempplot.gif"); print PLOT $im->gif; close(PLOT); # copy the image to its final destination and make sure it is owned # by the right person. system "cp /tmp/tempplot.gif /home/nexus/.public_html/tempplot.gif"; system "chown nexus.users /home/nexus/.public_html/tempplot.gif"; system "chmod 0644 /home/nexus/.public_html/tempplot.gif"; digitemp-3.6.0+dfsg1/perl/digitemp_mysql.pl0000755000175000017500000000534010632073746017371 0ustar ryanryan#!/usr/bin/perl -W # DigiTemp MySQL logging script # Copyright 2002 by Brian C. Lane # 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., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA # # -------------------------[ HISTORY ]------------------------------------- # 01/08/2004 The storage definition should have been decimal(6,2) instead # bcl of decimal(3,2). # See http://www.mysql.com/doc/en/Numeric_types.html for a # good description of how decimal(a,b) works. # # 08/18/2002 Putting together this MySQL logging script for the new # bcl release of DigiTemp. # # ------------------------------------------------------------------------- # CREATE table digitemp ( # dtKey int(11) NOT NULL auto_increment, # time timestamp NOT NULL, # SerialNumber varchar(17) NOT NULL, # Fahrenheit decimal(6,2) NOT NULL, # PRIMARY KEY (dtKey), # KEY serial_key (SerialNumber), # KEY time_key (time) # ); # # GRANT SELECT,INSERT ON digitemp.* TO dt_logger@localhost # IDENTIFIED BY 'TopSekRet'; # # ------------------------------------------------------------------------- use DBI; # Database info my $db_name = "digitemp"; my $db_user = "dt_logger"; my $db_pass = "TopSekRet"; # The DigiTemp Configuration file to use my $digitemp_rcfile = "/home/brian/digitemp.cfg"; my $digitemp_binary = "/home/brian/bin/digitemp"; my $debug = 0; # Connect to the database my $dbh = DBI->connect("dbi:mysql:$db_name","$db_user","$db_pass") or die "I cannot connect to dbi:mysql:$db_name as $db_user - $DBI::errstr\n"; # Gather information from DigiTemp # Read the output from digitemp # Output in form SerialNumberTemperature in Fahrenheit open( DIGITEMP, "$digitemp_binary -q -a -o\"%R %.2F\" -c $digitemp_rcfile |" ); while( ) { print "$_\n" if($debug); chomp; ($serialnumber,$temperature) = split(/ /); my $sql="INSERT INTO digitemp SET SerialNumber='$serialnumber',Fahrenheit=$temperature"; print "SQL: $sql\n" if($debug); $dbh->do($sql) or die "Can't execute statement $sql because: $DBI::errstr"; } close( DIGITEMP ); $dbh->disconnect; digitemp-3.6.0+dfsg1/perl/inc_temp0000755000175000017500000000542210632073746015527 0ustar ryanryan#!/usr/bin/perl -w # # DigiTemp webpage include script # Copyright 1997-2001 by Brian C. Lane www.brianlane.com # 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., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA # # # Read the temperature logfile, write an include file for the webpage. # # Sensor #0 is the Window # Sensor #1 is the inside of the Linux box # # Dec 18 21:46:47 Sensor 0 C: 8.81 F: 47.86 # Dec 18 21:46:47 Sensor 1 C: 26.41 F: 79.54 # # Directory and filename of the webpage include file to create $ftp_src_dir = "/tmp/"; $ftp_src_file = "nexus_temp.inc"; # Open the file for output open( INCFILE, ">$ftp_src_dir$ftp_src_file") || die "Can't open $ftp_src_dir$ftp_src_file"; # Write the temperatures to the file print INCFILE "
\n"; print INCFILE "
\n"; print INCFILE "The current temperatures are:

\n"; # Run tail -2 /var/log/temperature and parse the output # The -2 depends on the number of sensors that you have. open( TEMPLOG, "tail -2 /var/log/temperature |") || die "Can't fork: $!"; while( ) { # Get the time and date, sensor number, temperature in c and f ($month,$day,$time,$d1,$sensor,$d1,$centigrade,$d1,$fahrenheight) = split( " ", $_ ); # Print sensor specific messages # The \xB0 is supposed to be a degree symbol. It seems to work for some # systems but not for others if( $sensor eq '0' ) { print INCFILE "The modems are $fahrenheight\xB0 F ($centigrade\xB0 C)
\n"; } if( $sensor eq '1' ) { print INCFILE "The room is a "; if( $fahrenheight < 40.0 ) { print INCFILE "Freezing"; } if( $fahrenheight >= 40.0 and $fahrenheight < 70.0 ) { print INCFILE "Chilly"; } if( $fahrenheight >= 70.0 and $fahrenheight < 80.0 ) { print INCFILE "Comfortable"; } if( $fahrenheight >= 80.0 and $fahrenheight < 100.0 ) { print INCFILE "Balmy"; } if( $fahrenheight >= 100.0 ) { print INCFILE "Blistering"; } print INCFILE " $fahrenheight\xB0 F ($centigrade\xB0 C)
\n"; } } print INCFILE "Last updated: $month $day $time
\n"; print INCFILE "

\n"; close( TEMPLOG ); close( INCFILE ); # done! digitemp-3.6.0+dfsg1/perl/README0000644000175000017500000000464410632073746014670 0ustar ryanryanDigitemp v2.6 Copyright 1996-2002 by Brian C. Lane Here are a few useful perl scripts for you to use with DigiTemp. Most of them need customization for your specific circumstances. Some these scripts are old, as I now use the RRD tool to graph and log data. The digitemp_sql.pl script is new, and has not been tested extensivly yet, but should work for users familiar with the MySQL database system. inc_temp Build a file suitable for including into a server side include webpage (or modify it to create the whole webpage. This script operates on a logfile output from digitemp when running with the -l option. rem_temp Create an include file as in inc_temp and then send it to a server via FTP. This script operates on a logfile output from digitemp when running with the -l option. maxplot Create a GIF image of the temperature graph. This script operates on a logfile output from digitemp when running with the -l option. check_digitemp.pl This is a NetSaint/Nagios (www.nagios.com) script that uses DigiTemp to check temperatures on monitored machines. digitemp_sql.pl MySQL database logging of temperatures. This is a new script, it logs the serial number and temperature in Fahrenheit to a MySQL database. I assume that you are familiar with the care and feeding of your database so that I can skip over the simple stuff and get to the point: Create a new database named digitemp: mysqladmin create digitemp -u root -p Edit the grant_mysql.sql file and change the password and optionally the username. Grant access to the new database: mysql mysql -u root -p < mysql_grant.sql Create the database table: mysql digitemp -u root -p < make_mysql.sql Edit the digitemp_mysql.pl script. Change the password to the one you used above, optionally change the username. Point the digitemp_rcfile variable to the DigiTemp config file that you have previously created using digitemp -i -c rcfile I recommend using one other than .digitemprc so that it isn't accidently erased when you run digitemp -i from your home directory. Make sure the path to the digitemp binary is correct. It is specified by the $digitemp_binary variable. Setup a cron job to log temperatures to the database at regular intervals: */5 * * * * /home/brian/bin/digitemp_mysql.pl At this time I have not written any logging or graphing scripts to deal with the MySQL temperature data. digitemp-3.6.0+dfsg1/perl/check_digitemp.pl0000755000175000017500000001776711055341454017313 0ustar ryanryan#!/usr/bin/perl -w # check_digitemp.pl Copyright (C) 2002 by Brian C. Lane # # This is a NetSaint plugin script to check the temperature on a local # machine. Remote usage may be possible with SSH # # 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 # AUTHORS OR COPYRIGHT HOLDERS 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. # # =========================================================================== # Howto Install in NetSaint (tested with v0.0.7) # # 1. Copy this script to /usr/local/netsaint/libexec/ or wherever you have # placed your NetSaint plugins # # 2. Create a digitemp config file in /usr/local/netsaint/etc/ # eg. digitemp -i -s/dev/ttyS0 -c /usr/local/netsaint/etc/digitemp.conf # # 3. Make sure that the webserver user has permission to access the serial # port being used. # # 4. Add a command to /usr/local/netsaint/etc/commands.cfg like this: # command[check-temp]=$USER1$/check_digitemp.pl -w $ARG1$ -c $ARG2$ \ # -t $ARG3$ -f $ARG4$ # (fold into one line) # # 5. Tell NetSaint to monitor the temperature by adding a service line like # this to your hosts.cfg file: # service[kermit]=Temperature;0;24x7;3;5;1;home-admins;120;24x7;1;1;1;; \ # check-temp!65!75!1!/usr/local/netsaint/etc/digitemp.conf # (fold into one line) # 65 is the warning temperature # 75 is the critical temperature # 1 is the sensor # (as reported by digitemp -a) to monitor # digitemp.conf is the path to the config file # # 6. If you use Centigrade instead of Fahrenheit, change the commands.cfg # line to include the -C argument. You can then pass temperature limits in # Centigrade in the service line. # # =========================================================================== # Howto Install in Nagios (tested with v1.0b4) # # 1. Copy this script to /usr/local/nagios/libexec/ or wherever you have # placed your Nagios plugins # # 2. Create a digitemp config file in /usr/local/nagios/etc/ # eg. digitemp -i -s/dev/ttyS0 -c /usr/local/nagios/etc/digitemp.conf # # 3. Make sure that the webserver user has permission to access the serial # port being used. # # 4. Add a command to /usr/local/nagios/etc/checkcommands.cfg like this: # # #DigiTemp temperature check command # define command{ # command_name check_temperature # command_line $USER1$/check_digitemp.pl -w $ARG1$ -c $ARG2$ \ # -t $ARG3$ -f $ARG4$ # (fold above into one line) # } # # 5. Tell NetSaint to monitor the temperature by adding a service line like # this to your service.cfg file: # # #DigiTemp Temperature check Service definition # define service{ # use generic-service # host_name kermit # service_description Temperature # is_volatile 0 # check_period 24x7 # max_check_attempts 3 # normal_check_interval 5 # retry_check_interval 2 # contact_groups home-admins # notification_interval 240 # notification_period 24x7 # notification_options w,u,c,r # check_command check_temperature!65!75!1! \ # /usr/local/nagios/etc/digitemp.conf # (fold into one line) # } # # 65 is the warning temperature # 75 is the critical temperature # 1 is the sensor # (as reported by digitemp -a) to monitor # digitemp.conf is the path to the config file # # 6. If you use Centigrade instead of Fahrenheit, change the checkcommands.cfg # line to include the -C argument. You can then pass temperature limits in # Centigrade in the service line. # # =========================================================================== # Modules to use use strict; use Getopt::Std; # Define all our variable usage use vars qw($opt_c $opt_f $opt_t $opt_w $opt_F $opt_C $temperature $conf_file $sensor $temp_fmt $crit_level $warn_level $null %exit_codes $percent $fmt_pct $verb_err $command_line); # Predefined exit codes for NetSaint %exit_codes = ( 'OK' , 0, 'WARNING' , 1, 'CRITICAL', 2, 'UNKNOWN' ,3,); # Default to Fahrenheit input and result (use -C to change this) $temp_fmt = 3; # Get the options if ($#ARGV le 0) { &usage; } else { getopts('f:t:FCc:w:'); } # Shortcircuit the switches if (!$opt_w or $opt_w == 0 or !$opt_c or $opt_c == 0) { print "*** You must define WARN and CRITICAL levels!"; &usage; } # Check if levels are sane if ($opt_w >= $opt_c) { print "*** WARN level must not be greater than CRITICAL when checking temperature!"; &usage; } $warn_level = $opt_w; $crit_level = $opt_c; # Default sensor to read is #0 if(!$opt_t) { $sensor = 0; } else { $sensor = $opt_t; } # Default config file is /etc/digitemp.conf if(!$opt_f) { $conf_file = "/etc/digitemp.conf"; } else { $conf_file = $opt_f; } # Check for config file if( !-f $conf_file ) { print "*** You must have a digitemp.conf file\n"; &usage; } if($opt_C) { $temp_fmt = 2; } # Read the output from digitemp # Output in form 0\troom\tattic\tdrink open( DIGITEMP, "/usr/local/bin/digitemp -c $conf_file -t $sensor -q -o $temp_fmt |" ); # Process the output from the command while( ) { # print "$_\n"; chomp; if( $_ =~ /^nanosleep/i ) { print "Error reading sensor #$sensor\n"; close(DIGITEMP); exit $exit_codes{'UNKNOWN'}; } else { # Check for an error from digitemp, and report it instead if( $_ =~ /^Error.*/i ) { print $_; close(DIGITEMP); exit $exit_codes{'UNKNOWN'}; } else { ($null,$temperature) = split(/\t/); } } } close( DIGITEMP ); if( $temperature and $temperature >= $crit_level ) { print "Temperature CRITICAL - Sensor #$sensor = $temperature "; if( $temp_fmt == 3 ) { print "F\n"; } else { print "C\n"; } exit $exit_codes{'CRITICAL'}; } elsif ($temperature and $temperature >= $warn_level ) { print "Temperature WARNING - Sensor #$sensor = $temperature "; if( $temp_fmt == 3 ) { print "F\n"; } else { print "C\n"; } exit $exit_codes{'WARNING'}; } elsif( $temperature ) { print "Temperature OK - Sensor #$sensor = $temperature "; if( $temp_fmt == 3 ) { print "F\n"; } else { print "C\n"; } exit $exit_codes{'OK'}; } else { print "Error parsing result for sensor #$sensor\n"; exit $exit_codes{'UNKNOWN'}; } # Show usage sub usage() { print "\ncheck_digitemp.pl v1.0 - NetSaint Plugin\n"; print "Copyright 2002 by Brian C. Lane \n"; print "See source for License\n"; print "usage:\n"; print " check_digitemp.pl -t -f -w -c \n\n"; print "options:\n"; print " -f DigiTemp Config File\n"; print " -t DigiTemp Sensor #\n"; print " -F Temperature in Fahrenheit\n"; print " -C Temperature in Centigrade\n"; print " -w temperature temperature >= to warn\n"; print " -c temperature temperature >= when critical\n"; exit $exit_codes{'UNKNOWN'}; } digitemp-3.6.0+dfsg1/perl/grant_mysql.sql0000644000175000017500000000012410632073746017056 0ustar ryanryanGRANT SELECT,INSERT ON digitemp.* TO dt_logger@localhost IDENTIFIED BY 'TopSekRet'; digitemp-3.6.0+dfsg1/perl/make_mysql.sql0000644000175000017500000000036710632073746016671 0ustar ryanryanCREATE table digitemp ( dtKey int(11) NOT NULL auto_increment, time timestamp NOT NULL, SerialNumber varchar(17) NOT NULL, Fahrenheit decimal(6,2) NOT NULL, PRIMARY KEY (dtKey), KEY serial_key (SerialNumber), KEY time_key (time) ); digitemp-3.6.0+dfsg1/dthowto.txt0000644000175000017500000000741111055611136015261 0ustar ryanryan Howto build a Serial Adapter for Dallas DS1820 temperature sensors Copyright (c) 2001 by Brian C. Lane All Rights Reserved The DigiTemp program for Linux, DOS and Windows 95 uses a simple serial port adapter to communicate with the Dallas DS1820 digital temperature sensors. These sensors use a protocol called One-Wire or Micro LAN (depending on which Dallas documentation you are reading). This protocol requires only a ground and a data wire to the device. All power is derived from the data line while it is idle. The protocol is NOT RS232! The adapter converts the RS232 voltages into the +5v needed to communicate with the DS1820. Each byte sent to the serial port represents one data bit to the DS1820. See Dallas Semiconductor App Note #74 for more information, or the sourcecode for DigiTemp. How To build an adapter ----------------------- If you want a schematic diagram you need to look at page 20 of App. Note #74 from Dallas Semiconductor ( ) Parts List ---------- 1 DB-25 connector or DB-9 connector 1 1.5k ohm resistor 2 1N5818 Schottky Diode 1 1N5228 3.9v Zener Diode 1 1N5234 6.2v Zener Diode 1 2 position terminal block (for connecting the sensors to adapter) Wire cutters and a soldering iron. In this document I will refer to the pin functions. The pin numbers for DB-25 and DB-9 are as follows: Name DB-25 DB-9 ---- ----- ---- DTR 20 4 RXD 3 2 TXD 2 3 GND 1,7 5 NOTE: I have not built a DB-9 version myself. Please let me know if you successfully build one or have problems with it. On the DB-25 pins 1 and 7 must BOTH be connected together. Step Description ------------------------------------------------------------------------ 1. Solder the 1N5228 3.9v Zener between GND and DTR with the Cathode(the stripe) towards DTR. 2. Solder the 1.5k ohm resistor between RXD and TXD. 3. Solder one of the 1N5818 diodes between RXD and TXD with the Cathode(the stripe) towards RXD. 4. Solder the other 1N5818 diode between RXD and DTR with the Cathode(the stripe) towsrds DTR. 5. Solder the 1N5234 6.2v Zener between RXD and DTR with the Cathode(the stripe) towards DTR. 6. Solder RXD to one pin of the terminal block and paint it black. This is the GND connection for the sensors. 7. Solder DTR to the other pin of the terminal block and paint it red. This is the DATA connection for the sensors. There! Now you have an adapter. Connecting the sensors ---------------------- You need to connect to wires to the sensor to attach to the terminal block. If you look at the sensor so that the label is towards you, with the pins facing down the pins are from left to right: 1. GND 2. DATA 3. +5v Solder your wires to GND and DATA and connect them to the terminal block and you're done! Be careful not to overheat the sensor while soldering to it. My method is to tin the legs quickly and let them cool off (while tinning the others) and then to tin the wires, then attach them quickly with a minimum of heat applied. One additional note: Because of the voltage(and current) drop across the resistor this adapter isn't capable of providing enough current to read temperatures above about +70C. This is a limitation of the design, not an error with the DS1820 or the software. If you have any questions or comments, email me at bcl@brianlane.com or subscribe to the digitemp mailing list by sending a blank email to digitemp-subscribe@brianlane.com Brian Lane bcl@brianlane.com http://www.brianlane.com March 13, 2001 digitemp-3.6.0+dfsg1/ChangeLog0000644000175000017500000004643611055611675014624 0ustar ryanryan08/27/2008 Gathering up patches for a v3.6.0 release. Changes Include: - Releasing new version with these changes: - Updated to the .spec file from Fedora9 - DS2490 now suppresses the 'Found usb ...' output - Support for compiling under DARWIN - Current reading added to DS2438 - DS28EA00 support added - Tabbed output of 0.00 on CRC errors with log type -o2 or -o3 - New manpage from Debian digitemp maintainer 01/01/2007 Released v3.5.0 12/26/2006 Adding DS1923 Hygrosens Logger support from Tomasz Nowak Moved all of the history to ChangeLog 12/25/2006 Added Cygwin support Fixing ambiguous error messages (eg. blank config file or blank serial device). 06/25/2005 Logging output for DS2438 is not consistent with the other outputs. When -o2 and -o3 are used the temperatures for the DS2438 devices are output. The -H option can still be used to customize the DS2438 output when not using the -o options. 02/03/2004 Broke DS9097 support with my owWriteBytePower() return code check in digitemp.c in v3.3.1, so I applied the new DS9097 performance patch from Erik Rigtorp and changed owLevel in the ds9097 code to return the value called with to fake out the higher level code. Added FREEBSD to the typedef section of ownet.h, maybe this will fix some of those problems. 02/01/2004 Fixed DS2490 USB adapter support. Fixed Makefile so that it doesn't need to be edited for USB support. 01/25/2004 A user reported a bug in the humidity temperature, it wasn't converting negative temperatures correctly. I also see a potential problem with the DS18B20 and DS1822 which use a short int type and depend on it being 16 bits so that the sign comes out correct. But can we count on a short int always being 16 bits? I need to look into it. 01/10/2004 I'm trying to wrap up all the patches I've received int a new release v3.3.0 with humidity and DS2438 support. Added code from Eric Wilde to do humidity calculations for the AAG TAI-8540 humidity sensor. Adding patches for OpenBSD from Måns Nilsson. Changing the binary names that are generated to differentiate between DS9097, DS9097U and DS2490 (usb) adapter support. The USB support still doesn't work right. It searches the LAN ok, but needs to be root to do so, and doesn't read properly. I'll deal with it in the next release I guess. Added lockfiles. This requires either setting the binary to group lock (chmod g+s;chown .lock digitemp_*) or adding the user who will be running it to the lock group. 11/29/2003 Trying to get a first pass at DS2438 (A/D & Battery monitor) support up and running. Found a bug, init wouldn't record counters found on branches of a hub. 10/27/2003 Added patch from Sven Geggus to allow -n0 to make it run in an infinite loop. Need to check for exit conditions and clean up logfile, serial port, etc. in a nice manner. 08/13/2003 Adding DS2490 USB to 1-wire adapter support. Bumping the version number to 3.3.0 without a release of 3.2.1 06/14/2003 Made change to hub search from Jesús Roncero, it wouldn't work right if run with -q (a owFirst was inside the quiet check). Also adding the manpage created by Jesú. Version changed to 3.2.1 05/24/2003 Adding a banner that reports what library the binary was compiled for (DS9097 or DS9097U). Adjusted the makefile a bit, change the dist to be one of dist-9097 or dist-9097u to build for the right target. 05/23/2003 Adding kludges for USB to Serial adapter. Added a loop of 10 tries to the DS2480Detect routine. Added DEBUG_USERIAL compile time wrappers for diagnostic information about the ReadCOM routine. Part of the key to this is the delay used in ReadCOM, its just too short for use with the USB to serial adapter. I've changed it to 1 second + 10-15mS -- I'm not sure that the global_msec is really needed with the longer timeout time, its a fail-safe anyway; the character ought to come back a long time before the timeout. Changed version to v3.2.0 02/14/2003 Adding logging of read values. Need to change the way it handles building the output string. It works, but the counter really needs its own format string. Kinda hard to automatically integrate it into the current temperature oriented format string. 02/12/2003 Adding more code... Needs more work, the family code may be buried in the coupler linked list. I may need to move the decision as to how to read it to after it finds the coupler and turns it on. Change read_temp to read_sensor. device selection is common to all devices, then switch based on the serial number finally selected (saved as it is selected). 02/06/2003 Changed version number to v3.1.0 Adding support for counters Happy 92nd Birthday to Ronald Reagan! 01/10/2003 Finally, humidity is working, thanks in large part to work by Eric Wilde. Need to add logging of DS2438. I think it will be hard-coded, if it needs to be in another format it can be parsed with perl or python or whatever. Fixed a bug that wasn't allowing %% to be embedded in the format specifier. Adding lockfile support using the lockdev library under Linux. Wrapping it in LINUX checks until other systems indicate that they can use it. Lockfiles are working, but - the binary has to be sgid to the lock group so that it can access /var/lock, adding the user to the lock group would also accomplish this. 01/08/2003 Still trying to get DS2438 and Humidity support working Also changing strcpy to strncpy, dunno why they weren't already using it. 01/04/2003 Adding DS2438 based humidity support from Eric Wilde. 11/21/2002 Changed sleep method to use less CPU cycles, thanks to peter enderborg for pointing it out. 11/19/2002 Reviewing massive changes from Erik Rigtorp, he has added a userial compatible version of the passive adapter code. I am creating a new Makefile that will work for all systems and allow selection of the adapter at build time. Thanks for this version go to Erik Rigtorp for adding the userial compatible passive code. His webpage can be found at http://erkki.g0ds.org/ Thanks also go out to Kevin Pedigo for his help in getting the new Makefile up and running. Kevin is the current President of KPLUG (www.kplug.org/~kevinp) Improved the sleep method when reading sensors multiple times so that it doesn't use 100 CPU while waiting. Thanks to peter enderborg for pointing this out. Changed version # to v3.0.0 08/21/2002 Small bug with -i crept in, it wants another command to be present, it won't just initalize. 08/18/2002 Added %N token to allow the time in seconds since Epoch to be selected in the output. Added module for NetSaint/Nagios to perl directory, it is named check_digitemp.pl Added a MySQL logging script to perl directory, it is named digitemp_mysql.pl Added check for serial port permissions and nice error output if the user doesn't have +rw on the selected port. Removed limitation on -i being the only command. It can be combined with other commands again. Changed to v2.6 08/16/2002 Adding %N token to output seconds since Epoch, which is masked by my use of %s for the sensor number. I don't want to remove %s, because that would break old code. So %N now maps to %s in the strftime format. The check for commands is too strict, it isn't allowing -i to be combined with any of the other commands. Added permission checking on the serial device with a clean exit if the user doesn't have access to the serial device. 06/23/2002 Releasing new version today. Really! Making -q turn off the extra output I added for initalizing the 1-wire lan. 06/08/2002 Adding patches from John. exit() codes are now #defines and .digitemprc now outputs the serial numbers as hex instead of decimal. But maintains backwards compatibility until a new .digitemprc is written. Output format string now includes an option to output the Sensor's serial number in hex (%R). 06/08/2002 Made changes suggested by John Stoffel. Consisting mostly of code reorganizations. The one new feature is the %R format specifier for the log output string which inserts the hex serial number of the sensor into the output. We changed the way command line arguments are processed, so getopt is only called once, and added a check to make sure only 1 of the action commands is specified and complain otherwise. Changed to v2.5 05/11/2002 Adding more changes from John Stoffel 05/08/2002 Integrating changes for Solaris, AIX, FreeBSD from John Stoffel. Changes to getopt initial settings, Makefile and include files. 05/06/2002 Adding changes and fixes from DT v2.5 for Windows. Family code for DS1822 was wrong, it is really 0x22 Lots of changes to the read_temp routine, added a better scratchpad dump routine (previous one only worked for the DS1820). Quite a bit needs to be changed, I have switched to using a structure to store the sensor and coupler lists. I updated the core temperature read routine, the lan walk and device search routines. Reading when using a hub is now faster when reading multiple devices on the same hub segment. 01/15/2002 Cleaning up, preparing for release 01/15/2002 Added support for DS2409 one-wire couplers like those used in Simon Atkin's hub. www.simat.enta.net Converted to Dallas Semi's userial v3.00 one-wire library. Version changed to v2.3 Added a -w command to walk the entire one-wire LAN and show all device serial numbers with a descriptive family type. Thanks to Ted Frohling for the loan of the one-wire Hub. 01/14/2002 Adding support for reading sensors on DS2409 couplers. 01/13/2002 Walking the tree now works -- after changing the swt1f.c routine to use the Smart-On Main command while searching for devices (otherwise it only finds the first). Adding support for Coupler to the main program. Init now works, writing .digitemprc now works. Read .digitemprc appears to work. Need to add reading of specified sensors and of all sensors. 01/12/2002 Adding a diagnostic walk of the attached network, working on DS2409 MicroLAN Coupler support. Added release1WireNet calls before all exit calls. Switching to the userial library v3.0.0, I seem to have run into a problem with the old library and I cannot read either of my DS9097U adapters with v2.2 digitemp code. 05/26/2001 The 18B20 and 1822 patch didn't work. It was reading the wrong scratchpad registers. (2,1 instead of 1,0). Changed version to v2.2 03/16/2001 Integrating the AIX patch from Ewan Leith It amounts to return value checking on getopt and changes in the wirelnk.c file. Adding DS1822 and DS18B20 changes from Roland Roberts 03/16/2001 Integrated the AIX changes Integrated the DS1822 and DS18B20 patch Added the patch for DS1822 and DS18B20 support. 03/13/2001 Version 2.1 release Added detection of a temperature glitch in the DS1820 Added detection of the DS18S20's 85 degree C error state Added output of error conditions to stderr Bad reads will now insert zeros instead of skipping the sensor If a read fails it is retried 3 times before giving up on that sensor. The remainder of the sensors are still attempted. Added a command line option (-c) to allow the configuration file to be specified. Added a couple more scripts to the rrdb directory. 03/05/2001 Adding a command line option to specify the configuration file to use. -c config_file will override the default of .digitemprc 02/17/2001 If there is an error with strong pullup on/off it shouldn't abort the conversion! Just log an error to stderr. 01/31/2001 Added a dummy temperature output when a sensor cannot be read. It outputs a 0 so that scripts like my grapher don't get confused and log the wrong sensor in the wrong place. An error message is also output to stderr. 01/29/2001 Oops. It seems that I missed the line in the DS1820 datasheet that says Vdd needs to be tied to GND for Parasite power to work correctly. Various curses come to mind. The DS1820 works better than the DS18S20 with Vdd floating but this probably explains the infrequent glitches I saw before adding the DS18S20s. 01/15/2001 Still getting glitches. Adding a reset and delay before retry 01/14/2001 Changed Version number to 2.1 I now have 2 DS18S20 sensors which supposedly fix the Temperature accuracy problems of the DS1820 (see the ds1820-report.pdf from Dallas). But now I get a huge number of glitches in the DS18S20's readings. The DS18S20 has an error condition, but it is +85C and the glitches I am seeing are because DigiTemp doesn't output anything at all for the DS18S20's reading. Adding a check for the DS18S20's error condition: LSB = 0xAA MSB = 0x00 COUNT_REMAIN = 0x0C COUNT_PER_C = 0x10 If this error case is encountered, the reading should be repeated. If it comes up again, use it. There is also a glitch possible in the DS1820 that exhibits itself by COUNT_PER_C - COUNT_REMAIN = 1, this should be checked for, and the reading repeated and the next result used. The problem with no reading from the device seems to happen when MLanAccess is called. There is no good way to tell what the problem is, so I will change the code to try 3 times before failing. Changes are in read_temp. 01/04/2000 Changing the default read timeout to 1000mS. I had problems with it set to 500mS and a 30' sensor wire (the reading was low by about 10 degrees). 01/04/2000 Version 2.0 release Adding support for the DS9097-U adapter for the Linux version. The Solaris version will need changes to be able to support the DS9097-U. Changed license to GNU Public License v2.0 Added the -q option to make the banner disappear. 01/01/2000 Well, no release last year. Adding -q to make the banner dissapear for batchfiles that want to get the output directly. 12/28/1999 Changed Version number to 2.0 Adding GNU public license Changing this code to use the DS9097-U adapter 06/03/1999 Finishing this thing up. 06/02/1999 Use 2 logging routines, log_time to log a single line per sensor with optional time data and log_str to log a single line for multiple sensors with elapsed time at the beginning of the line. 05/29/1999 Added 2 new init file tags, LOG_FORMAT and LOG_TYPE New formatting works, need to clean up the logic now. 05/27/1999 Adding user specified format string. To use it, first parse out the digitemp specific stuff and create a new string to feed into strftime, with the sensor, temperature already set. 05/24/1999 Adding a output specifier string, this will allow users to configure the output to look however they want it to. The format string uses strftime tokens plus 3 special ones for digitemp - %s for sensor #, %C for centigrade, %F for fahrenheit 05/23/1999 Adding Solaris support via -DSOLARIS define Fixing the time problems once and for all, using localtime in the log_line routine. The user should have TZ set correctly for their timezone. This has been tested and works correctly. Changed version number to v1.3 05/23/1999 Adding Solaris changes, donated by a user. Removing libc5 binaries, I no longer have a libc5 system Fixing the time problems with logging 01/14/1999 A user in Sweden (and another in Finland) discovered a long standing bug. In do_temp I should have been using 0x100 instead of 0xFF for the subtraction. This caused temperatures below 0 degrees C to jump up 1 degree as it decreased. This is fixed. Changed version number to v1.2 10/20/1998 Adding new features from DOS version to keep things consistent. Removing the debug command, not used anyway. Added a free() to error condition edit from read_rcfile() Set some cases of freeing to = NULL, also freed the rom list before doing a search rom (searchROM checks too, but this is the right place for it). 08/31/1998 Adding a check for family 0x10 so that we can read DS1820s while they are on a network that includes other 1-wire devices. Fixed a problem with freeing uninitalized rom_list when starting a SearchROM. Not sure why this never appeared before. 03/06/1998 Adding a -d debug level to help figure out why this thing is no longer working. 03/13/1997 Error in CRC calculation. Wrong # of bytes. Error with 3 sensors. Sometimes doesn't store correct ROM data to .digitemprc -- need to malloc more memory dummy! 03/08/1997 Adding user defined timeouts for failure and for the read delay. 01/24/1997 Changed over to correct baud rate and 6 bits @ 115.2k ROM search function is now working. All low level code is functioning except for Alarm Search. Starting to move into a seperate object file with API for users to write their own code with. 01/22/97 Working on ROM search routine, double cannot handle a full 64 bits for some reason, converting to 64 byte array for each bit. 01/19/1997 Rewriting for new interface. This programs handles all the low level communications with the temperature sensor using the 115200k serial adapter. 01/02/1996 Rewriting this code to be more user friendly digitemp-3.6.0+dfsg1/digitemp.spec0000644000175000017500000000522111055611522015502 0ustar ryanryan%define with_libusb 1 Summary: Dallas Semiconductor 1-wire device reading console application Name: digitemp Version: 3.6.0 Release: 1%{?dist} License: GPLv2+ Group: Applications/System URL: http://www.digitemp.com/ Source0: http://www.digitemp.com/software/linux/%{name}-%{version}.tar.gz Source1: dthowto.txt Source2: DS9097_Schematic.gif Patch0: digitemp-cflags.patch %if %{with_libusb} BuildRequires: libusb-devel %endif BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) %description DigiTemp is a simple to use console application for reading values from Dallas Semiconductor 1-wire devices. Its main use is for reading temperature sensors, but it also reads counters and understands the 1-wire hubs with devices on different branches of the network. DigiTemp now supports the following 1-wire temperature sensors: DS18S20 (and DS1820), DS18B20, DS1822, the DS2438 Smart Battery Monitor, DS2422 and DS2423 Counters, DS2409 MicroLAN Coupler (used in 1-wire hubs) and the AAG TAI-8540 humidity sensor. %prep %setup -q %patch0 -p1 -b .cflags cp -f %{SOURCE1} %{SOURCE2} . %build make ds9097 %{?_smp_mflags} make ds9097u %{?_smp_mflags} %if %{with_libusb} make ds2490 %{?_smp_mflags} %endif %install rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT{%{_bindir},%{_mandir}/man1} install -m 755 digitemp_DS9097 digitemp_DS9097U $RPM_BUILD_ROOT%{_bindir} %if %{with_libusb} install -m 755 digitemp_DS2490 $RPM_BUILD_ROOT%{_bindir} %endif iconv -f iso-8859-1 -t utf-8 -o digitemp.1.utf8 digitemp.1 install -m 644 digitemp.1.utf8 $RPM_BUILD_ROOT%{_mandir}/man1/%{name}.1 %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %doc ChangeLog COPYING COPYRIGHT CREDITS FAQ README TODO %doc dthowto.txt DS9097_Schematic.gif %{_bindir}/%{name}* %{_mandir}/man1/%{name}.* %changelog * Thu Aug 28 2008 Brian C. Lane 3.6.0-1 - Releasing new version with these changes: - Updated to the .spec file from Fedora9 - DS2490 now suppresses the 'Found usb ...' output - Support for compiling under DARWIN - Current reading added to DS2438 - DS28EA00 support added - Tabbed output of 0.00 on CRC errors with log type -o2 or -o3 - New manpage from Debian digitemp maintainer * Sun Feb 10 2008 Robert Scheck 3.5.0-3 - Rebuilt against gcc 4.3 * Tue Aug 28 2007 Robert Scheck 3.5.0-2 - Updated the license tag according to the guidelines * Sun Jan 07 2007 Robert Scheck 3.5.0-1 - Upgrade to 3.5.0 - Initial spec file for Fedora and Red Hat Enterprise Linux digitemp-3.6.0+dfsg1/src/0000755000175000017500000000000011055620247013617 5ustar ryanryandigitemp-3.6.0+dfsg1/src/ds9097.c0000644000175000017500000000003710632073746014730 0ustar ryanryanconst char dtlib[] = "DS9097"; digitemp-3.6.0+dfsg1/src/digitemp.c0000644000175000017500000024627511055426310015600 0ustar ryanryan/* ----------------------------------------------------------------------- DigiTemp Copyright 1996-2007 by Brian C. Lane 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA digitemp -w Walk the LAN & show all digitemp -i Initalize .digitemprc file digitemp -I Initialize .digitemprc w/sorted serial #s digitemp -s/dev/ttyS0 Set serial port (required) digitemp -cdigitemp.conf Configuration File digitemp -r1000 Set Read timeout to 1000mS digitemp -l/var/log/temperature Send output to logfile digitemp -v Verbose mode digitemp -t0 Read Temperature digitemp -q Quiet, no copyright banner digitemp -a Read all Temperatures digitemp -d5 Delay between samples (in sec.) digitemp -n50 Number of times to repeat. 0=forever digitemp -A Treat DS2438 as A/D converter digitemp -o1 Output format for logfile See description below digitemp -o"output format string" See description below digitemp -O"counter format" See description below digitemp -H"Humidity format" See description below Logfile formats: 1 = (default) - 1 line per sensor, time, C, F 1 line for each sample, elapsed time, sensor #1, #2, ... tab seperated 2 = Reading in C 3 = Reading in F The format string uses strftime tokens plus 6 special ones for digitemp - %s for sensor #, %C for centigrade, %F for fahrenheit, %R for hex serial number, %N for seconds since Epoch Humidity uses %h for the relative humidity in percent The counter format uses %n for the counter # and %C for the count in decimal Remember the case of the token is important! ======================================================================= See ChangeLog file for history of changes -----------------------------------------------------------------------*/ #include #include #include #include #if !defined(AIX) && !defined(SOLARIS) && !defined(FREEBSD) && !defined(DARWIN) #include #endif /* !AIX and !SOLARIS and !FREEBSD and !DARWIN */ #include #include #include #include #include #include #include #include #include "ad26.h" // Include endian.h #if DARWIN #include #endif #if FREEBSD #include #endif #if !defined(DARWIN) && !defined(FREEBSD) #include #endif #ifdef LINUX #ifndef OWUSB #ifdef LOCKDEV #include #endif #endif #endif #include "digitemp.h" #include "device_name.h" #include "ownet.h" #include "owproto.h" /* Setup the correct getopt starting point */ #ifdef LINUX #define GETOPTEOF -1 #define OPTINDSTART 0 #endif #ifdef CYGWIN #define GETOPTEOF -1 #define OPTINDSTART 0 #endif #ifdef AIX #define OPTINDSTART 0 #define GETOPTEOF 255 #endif #ifdef SOLARIS #define GETOPTEOF EOF #define OPTINDSTART 1 #endif #ifdef FREEBSD #define GETOPTEOF EOF #define OPTINDSTART 1 #endif #ifdef OPENBSD #define GETOPTEOF EOF #define OPTINDSTART 1 #endif #ifdef NETBSD #define GETOPTEOF EOF #define OPTINDSTART 1 #endif #ifdef DARWIN #define GETOPTEOF EOF #define OPTINDSTART 1 #endif #ifdef OTHER #define GETOPTEOF EOF #define OPTINDSTART 1 #endif /* For tracking down strange errors */ #undef BCL_DEBUG extern char *optarg; extern int optind, opterr, optopt; #if defined(FREEBSD) || defined(DARWIN) extern int optreset; #endif /* FREEBSD or DARWIN */ extern const char dtlib[]; /* Library Used */ char serial_port[40], /* Path to the serial port */ tmp_serial_port[40], serial_dev[40], /* Device name without /dev/ */ log_file[1024], /* Path to the log file */ tmp_log_file[1024], temp_format[80], /* Format for temperature readings */ tmp_temp_format[80], counter_format[80], /* Format for counter readings */ tmp_counter_format[80], humidity_format[80], /* Format for Humidity readings */ tmp_humidity_format[80], conf_file[1024], /* Configuration File */ option_list[40]; int read_time, /* Pause during read */ tmp_read_time, log_type, /* output format type */ tmp_log_type, num_cs = 0, /* Number of sensors on cplr */ opts = 0; /* Bitmask of flags */ struct _coupler *coupler_top = NULL; /* Linked list of couplers */ unsigned char Last2409[9]; /* Last selected coupler */ int global_msec = 10; /* For ReadCOM delay */ int global_msec_max = 15; /* ----------------------------------------------------------------------- * Print out the program usage * ----------------------------------------------------------------------- */ void usage() { printf(BANNER_1); printf(BANNER_2); printf(BANNER_3, dtlib ); /* Report Library version */ printf("\nUsage: digitemp [-s -i -I -U -l -r -v -t -a -d -n -o -c]\n"); printf(" -i Initalize .digitemprc file\n"); printf(" -I Initalize .digitemprc file w/sorted serial #s\n"); printf(" -w Walk the full device tree\n"); printf(" -s /dev/ttyS0 Set serial port\n"); printf(" -l /var/log/temperature Send output to logfile\n"); printf(" -c digitemp.conf Configuration File\n"); printf(" -r 1000 Read delay in mS\n"); printf(" -v Verbose output\n"); printf(" -t 0 Read Sensor #\n"); printf(" -q No Copyright notice\n"); printf(" -a Read all Sensors\n"); printf(" -d 5 Delay between samples (in sec.)\n"); printf(" -n 50 Number of times to repeat\n"); printf(" 0=loop forever\n"); printf(" -A Treat DS2438 as A/D converter\n"); printf(" -O\"counter format string\" See description below\n"); printf(" -o 2 Output format for logfile\n"); printf(" -o\"output format string\" See description below\n"); printf(" -H\"Humidity format string\" See description below\n"); printf("\nLogfile formats: 1 = One line per sensor, time, C, F (default)\n"); printf(" 2 = One line per sample, elapsed time, temperature in C\n"); printf(" 3 = Same as #2, except temperature is in F\n"); printf(" #2 and #3 have the data seperated by tabs, suitable for import\n"); printf(" into a spreadsheet or other graphing software.\n"); printf("\n The format string uses strftime tokens plus 5 special ones for\n"); printf(" digitemp - %%s for sensor #, %%C for centigrade, %%F for fahrenheit,\n"); printf(" %%R to output the hex serial number, and %%N for seconds since Epoch.\n"); printf(" The case of the token is important! The default format string is:\n"); printf(" \"%%b %%d %%H:%%M:%%S Sensor %%s C: %%.2C F: %%.2F\" which gives you an\n"); printf(" output of: May 24 21:25:43 Sensor 0 C: 23.66 F: 74.59\n\n"); printf(" The counter format string has 2 special specifiers:\n"); printf(" %%n is the counter # and %%C is the count in decimal.\n"); printf(" The humidity format uses %%h for the humidity in percent\n\n"); } /* ----------------------------------------------------------------------- * Free up all memory used by the coupler list * ----------------------------------------------------------------------- */ void free_coupler( int free_only ) { unsigned char a[3]; struct _coupler *c; c = coupler_top; while(c) { /* Turn off the Coupler */ if ( !free_only ) SetSwitch1F(0, c->SN, ALL_LINES_OFF, 0, a, TRUE); /* Free up the serial number lists */ if( c->num_main > 0 ) free( c->main ); if( c->num_aux > 0 ) free( c->aux ); /* Point to the next in the list */ coupler_top = c->next; /* Free up the current entry */ free( c ); c = coupler_top; } /* Coupler free loop */ /* Make sure its null */ coupler_top = NULL; } /* ----------------------------------------------------------------------- Convert degrees C to degrees F ----------------------------------------------------------------------- */ float c2f( float temp ) { return 32 + ((temp*9)/5); } /* ----------------------------------------------------------------------- Take the log_format string and parse out the digitemp tags (%*s %*C and %*F) including any format specifiers to pass to sprintf. Build a new string with the strftime tokens and the temperatures mixed together If humidity is <0 then it is invalid ----------------------------------------------------------------------- */ int build_tf( char *time_format, char *format, int sensor, float temp_c, int humidity, unsigned char *sn ) { char *tf_ptr, *lf_ptr, *lf_ptr2, *tk_ptr, token[80], temp[80]; if( !time_format || !format ) return 0; tf_ptr = time_format; lf_ptr = format; while( *lf_ptr ) { if( *lf_ptr != '%' ) { *tf_ptr++ = *lf_ptr++; } else { /* Found a token, decide if its one of ours... */ /* save initial pointer, grab everything up to... */ lf_ptr2 = lf_ptr; tk_ptr = token; /* At this point it has a potential format specifier, copy it over to the token variable, up to the alpha-numeric specifier. It needs to stop copying after it gets the alpha character */ while( isalnum( *lf_ptr ) || (*lf_ptr == '.') || (*lf_ptr == '*') || (*lf_ptr == '%') ) { *tk_ptr++ = *lf_ptr++; *tk_ptr = 0; /* Break out when the alpha character is copied over */ if( isalpha( *(lf_ptr-1) ) ) break; } /* see if the format specifier is digitemp or strftime */ switch( *(tk_ptr-1) ) { case 's' : /* Sensor number */ /* Change the specifier to a d */ *(tk_ptr-1) = 'd'; /* Pass it through sprintf */ sprintf( temp, token, sensor ); /* Insert this into the time format string */ tk_ptr = temp; while( *tk_ptr ) *tf_ptr++ = *tk_ptr++; break; case 'h' : /* Relative humidity % */ /* Change the specifier to a d */ *(tk_ptr-1) = 'd'; /* Pass it through sprintf */ sprintf( temp, token, humidity ); /* Insert this into the time format string */ tk_ptr = temp; while( *tk_ptr ) *tf_ptr++ = *tk_ptr++; break; case 'F' : /* Degrees Fahrenheit */ /* Change the specifier to a f */ *(tk_ptr-1) = 'f'; /* Pass it through sprintf */ sprintf( temp, token, c2f(temp_c) ); /* Insert this into the time format string */ tk_ptr = temp; while( *tk_ptr ) *tf_ptr++ = *tk_ptr++; break; case 'C' : /* Degrees Centigrade */ /* Change the specifier to a f */ *(tk_ptr-1) = 'f'; /* Pass it through sprintf */ sprintf( temp, token, temp_c ); /* Insert this into the time format string */ tk_ptr = temp; while( *tk_ptr ) *tf_ptr++ = *tk_ptr++; break; case 'R' : /* ROM Serial Number */ /* Change the specifier to a hex (x) */ *(tk_ptr-1) = 'X'; /* Insert the serial number in HEX, yes its ugly, but it works and saves using another temporary location and variable. */ sprintf( temp, "%02X%02X%02X%02X%02X%02X%02X%02X", sn[0],sn[1],sn[2],sn[3],sn[4],sn[5],sn[6],sn[7]); /* Insert this into the time format string */ tk_ptr = temp; while( *tk_ptr ) *tf_ptr++ = *tk_ptr++; break; case 'N' : /* Seconds since Epoch */ /* Change the specifier to a s and pass to time */ *(tk_ptr-1) = 's'; /* Intentional fall through */ default: /* Not something for us, copy it into the time format */ tk_ptr = token; while( *tk_ptr ) *tf_ptr++ = *tk_ptr++; break; } } } /* Terminate the string */ *tf_ptr = 0; return 1; } /* ----------------------------------------------------------------------- Take the log_format string and parse out the digitemp tags (%*s %*C and %*F) including any format specifiers to pass to sprintf. Build a new string with the strftime tokens and the temperatures mixed together ----------------------------------------------------------------------- */ int build_cf( char *time_format, char *format, int sensor, int page, unsigned long count, unsigned char *sn ) { char *tf_ptr, *lf_ptr, *lf_ptr2, *tk_ptr, token[80], temp[80]; if( !time_format || !format ) return 0; tf_ptr = time_format; lf_ptr = format; while( *lf_ptr ) { if( *lf_ptr != '%' ) { *tf_ptr++ = *lf_ptr++; } else { /* Found a token, decide if its one of ours... */ /* save initial pointer, grab everything up to... */ lf_ptr2 = lf_ptr; tk_ptr = token; /* Take numbers, astrix, period and letters */ while( isalnum( *lf_ptr ) || (*lf_ptr == '.') || (*lf_ptr == '*') || (*lf_ptr == '%') ) { *tk_ptr++ = *lf_ptr++; *tk_ptr = 0; } /* see if the format specifier is digitemp or strftime */ switch( *(tk_ptr-1) ) { case 's' : /* Sensor number */ /* Change the specifier to a d */ *(tk_ptr-1) = 'd'; /* Pass it through sprintf */ sprintf( temp, token, sensor ); /* Insert this into the time format string */ tk_ptr = temp; while( *tk_ptr ) *tf_ptr++ = *tk_ptr++; break; case 'F' : break; case 'n' : /* Show the page/counter # (0 or 1) */ /* Change the specifier to a d */ *(tk_ptr-1) = 'd'; /* Pass it through sprintf */ sprintf( temp, token, page ); /* Insert this into the time format string */ tk_ptr = temp; while( *tk_ptr ) *tf_ptr++ = *tk_ptr++; break; case 'C' : /* Counter reading, 32 bit value */ /* Change the specifier to a ld */ *(tk_ptr-1) = 'l'; *(tk_ptr) = 'd'; *(tk_ptr+1) = 0; /* Pass it through sprintf */ sprintf( temp, token, count ); /* Insert this into the time format string */ tk_ptr = temp; while( *tk_ptr ) *tf_ptr++ = *tk_ptr++; break; case 'R' : /* ROM Serial Number */ /* Change the specifier to a hex (x) */ *(tk_ptr-1) = 'X'; /* Insert the serial number in HEX, yes its ugly, but it works and saves using another temporary location and variable. */ sprintf( temp, "%02X%02X%02X%02X%02X%02X%02X%02X", sn[0],sn[1],sn[2],sn[3],sn[4],sn[5],sn[6],sn[7]); /* Insert this into the time format string */ tk_ptr = temp; while( *tk_ptr ) *tf_ptr++ = *tk_ptr++; break; case 'N' : /* Seconds since Epoch */ /* Change the specifier to a s and pass to time */ *(tk_ptr-1) = 's'; /* Intentional fall through */ default: /* Not something for us, copy it into the time format */ tk_ptr = token; while( *tk_ptr ) *tf_ptr++ = *tk_ptr++; break; } } } /* Terminate the string */ *tf_ptr = 0; return 1; } /* ----------------------------------------------------------------------- Print a string to the console or the logfile ----------------------------------------------------------------------- */ int log_string( char *line ) { int fd=0; if( log_file[0] != 0 ) { if( (fd = open( log_file, O_CREAT | O_WRONLY | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ) ) == -1 ) { printf("Error opening logfile: %s\n", log_file ); return -1; } if( write( fd, line, strlen( line ) ) == -1) perror("Error loging to logfile"); close( fd ); } else { printf( line ); } return 0; } /* ----------------------------------------------------------------------- Log one line of text to the logfile with the current date and time Used with temperatures ----------------------------------------------------------------------- */ int log_temp( int sensor, float temp_c, unsigned char *sn ) { char temp[1024], time_format[160]; time_t mytime; mytime = time(NULL); if( mytime ) { /* Build the time format string from log_format */ build_tf( time_format, temp_format, sensor, temp_c, -1, sn ); /* Handle the time format tokens */ strftime( temp, 1024, time_format, localtime( &mytime ) ); strcat( temp, "\n" ); } else { sprintf( temp, "Time Error\n" ); } /* Log it to stdout, logfile or both */ log_string( temp ); return 0; } /* ----------------------------------------------------------------------- Log one line of text to the logfile with the current date and time Used with counters ----------------------------------------------------------------------- */ int log_counter( int sensor, int page, unsigned long counter, unsigned char *sn ) { char temp[1024], time_format[160]; time_t mytime; mytime = time(NULL); if( mytime ) { /* Build the time format string from counter_format */ build_cf( time_format, counter_format, sensor, page, counter, sn ); /* Handle the time format tokens */ strftime( temp, 1024, time_format, localtime( &mytime ) ); strcat( temp, "\n" ); } else { sprintf( temp, "Time Error\n" ); } /* Log it to stdout, logfile or both */ log_string( temp ); return 0; } /* ----------------------------------------------------------------------- Log one line of text to the logfile with the current date and time Used with temperatures ----------------------------------------------------------------------- */ int log_humidity( int sensor, double temp_c, int humidity, unsigned char *sn ) { char temp[1024], time_format[160]; time_t mytime; mytime = time(NULL); if( mytime ) { /* Log the temperature */ switch( log_type ) { /* Multiple Centigrade temps per line */ case 2: sprintf( temp, "\t%3.2f", temp_c ); break; /* Multiple Fahrenheit temps per line */ case 3: sprintf( temp, "\t%3.2f", c2f(temp_c) ); break; default: /* Build the time format string from log_format */ build_tf( time_format, humidity_format, sensor, temp_c, humidity, sn ); /* Handle the time format tokens */ strftime( temp, 1024, time_format, localtime( &mytime ) ); strcat( temp, "\n" ); break; } } else { sprintf( temp, "Time Error\n" ); } /* Log it to stdout, logfile or both */ log_string( temp ); return 0; } /* ----------------------------------------------------------------------- Compare two serial numbers and return 1 of they match The second one has an additional byte indicating the main (0) or aux (1) branch. ----------------------------------------------------------------------- */ int cmpSN( unsigned char *sn1, unsigned char *sn2, int branch ) { int i; for(i = 0; i < 8; i++ ) { if( sn1[i] != sn2[i] ) { return 0; } } if( branch != sn2[8] ) { return 0; } /* Everything Matches */ return 1; } /* ----------------------------------------------------------------------- Show the verbose contents of the scratchpad ----------------------------------------------------------------------- */ void show_scratchpad( unsigned char *scratchpad, int sensor_family ) { char temp[80]; int i; if( log_file[0] != 0 ) { switch( sensor_family ) { case DS1820_FAMILY: sprintf( temp, " Temperature : 0x%02X\n", scratchpad[1] ); sprintf( temp, " Sign : 0x%02X\n", scratchpad[2] ); sprintf( temp, " TH : 0x%02X\n", scratchpad[3] ); sprintf( temp, " TL : 0x%02X\n", scratchpad[4] ); sprintf( temp, " Remain : 0x%02X\n", scratchpad[7] ); sprintf( temp, " Count Per C : 0x%02X\n", scratchpad[8] ); sprintf( temp, " CRC : 0x%02X\n", scratchpad[9] ); break; case DS18B20_FAMILY: case DS1822_FAMILY: case DS28EA00_FAMILY: sprintf( temp, " Temp. LSB : 0x%02X\n", scratchpad[1] ); sprintf( temp, " Temp. MSB : 0x%02X\n", scratchpad[2] ); sprintf( temp, " TH : 0x%02X\n", scratchpad[3] ); sprintf( temp, " TL : 0x%02X\n", scratchpad[4] ); sprintf( temp, " Config Reg. : 0x%02X\n", scratchpad[5] ); sprintf( temp, " CRC : 0x%02X\n", scratchpad[9] ); break; case DS2422_FAMILY: case DS2423_FAMILY: break; } /* sensor_family switch */ } else { switch( sensor_family ) { case DS1820_FAMILY: printf(" Temperature : 0x%02X\n", scratchpad[1] ); printf(" Sign : 0x%02X\n", scratchpad[2] ); printf(" TH : 0x%02X\n", scratchpad[3] ); printf(" TL : 0x%02X\n", scratchpad[4] ); printf(" Remain : 0x%02X\n", scratchpad[7] ); printf(" Count Per C : 0x%02X\n", scratchpad[8] ); printf(" CRC : 0x%02X\n", scratchpad[9] ); break; case DS18B20_FAMILY: case DS1822_FAMILY: case DS28EA00_FAMILY: printf( " Temp. LSB : 0x%02X\n", scratchpad[1] ); printf( " Temp. MSB : 0x%02X\n", scratchpad[2] ); printf( " TH : 0x%02X\n", scratchpad[3] ); printf( " TL : 0x%02X\n", scratchpad[4] ); printf( " Config Reg. : 0x%02X\n", scratchpad[5] ); printf( " CRC : 0x%02X\n", scratchpad[9] ); break; case DS2422_FAMILY: case DS2423_FAMILY: break; } /* sensor_family switch */ } /* if log_file */ /* Dump the complete contents of the scratchpad */ for( i = 0; i < 10; i++ ) { printf( "scratchpad[%d] = 0x%02X\n", i, scratchpad[i] ); } } /* ----------------------------------------------------------------------- Read the temperature from one sensor Return the high-precision temperature value Calculated using formula from DS1820 datasheet Temperature = scratchpad[1] Sign = scratchpad[2] TH = scratchpad[3] TL = scratchpad[4] Count Remain = scratchpad[7] Count Per C = scratchpad[8] CRC = scratchpad[9] count_per_C - count_remain (temp - 0.25) * -------------------------- count_per_C If Sign is not 0x00 then it is a negative (Centigrade) number, and the temperature must be subtracted from 0x100 and multiplied by -1 ----------------------------------------------------------------------- */ int read_temperature( int sensor_family, int sensor ) { char temp[1024]; /* For output string */ unsigned char lastcrc8, scratchpad[30], /* Scratchpad block from the sensor */ TempSN[8]; int x, j, try, /* Number of tries at reading device */ strong_err, /* Error with strong pullup? */ ds1820_try, /* Allow ds1820 glitch 1 time */ ds18s20_try; /* Allow DS18S20 error 1 time */ float temp_c, /* Calculated temperature in Centigrade */ hi_precision; x = 0; ds1820_try = 0; ds18s20_try = 0; temp_c = 0; for( try = 0; try < MAX_READ_TRIES; try++ ) { if( owAccess(0) ) { /* Convert Temperature */ if( !owWriteBytePower( 0, 0x44 ) ) { return FALSE; } /* Sleep for conversion second */ msDelay( read_time ); /* Turn off the strong pullup */ if( owLevel( 0, MODE_NORMAL ) != MODE_NORMAL ) { strong_err = 2; } /* Now read the scratchpad from the device */ if( owAccess(0) ) { /* Use Read_Scratchpad instead? */ /* Build a block for the Scratchpad read */ scratchpad[0] = 0xBE; for( j = 1; j < 10; j++ ) scratchpad[j] = 0xFF; /* Send the block */ if( owBlock( 0, FALSE, scratchpad, 10 ) ) { /* Calculate the CRC 8 checksum on the received data */ setcrc8(0, 0); for( j = 1; j < 10; j++ ) lastcrc8 = docrc8( 0, scratchpad[j] ); /* If the CRC8 is valid then calculate the temperature */ if( lastcrc8 == 0x00 ) { /* DS1822 and DS18B20 use a different calculation */ if( (sensor_family == DS18B20_FAMILY) || (sensor_family == DS1822_FAMILY) || (sensor_family == DS28EA00_FAMILY) || (sensor_family == DS1923_FAMILY) ) { short int temp2 = (scratchpad[2] << 8) | scratchpad[1]; temp_c = temp2 / 16.0; } /* Handle the DS1820 and DS18S20 */ if( sensor_family == DS1820_FAMILY ) { /* Check for DS1820 glitch condition */ /* COUNT_PER_C - COUNT_REMAIN == 1 */ if( ds1820_try == 0 ) { if( (scratchpad[7] - scratchpad[6]) == 1 ) { ds1820_try = 1; continue; } /* DS1820 error */ } /* ds1820_try */ /* Check for DS18S20 Error condition */ /* LSB = 0xAA MSB = 0x00 COUNT_REMAIN = 0x0C COUNT_PER_C = 0x10 */ if( ds18s20_try == 0 ) { if( (scratchpad[4]==0xAA) && (scratchpad[3]==0x00) && (scratchpad[7]==0x0C) && (scratchpad[8]==0x10) ) { ds18s20_try = 1; continue; } /* DS18S20 error condition */ } /* ds18s20_try */ /* Convert data to temperature */ if( scratchpad[2] == 0 ) { temp_c = (int) scratchpad[1] >> 1; } else { temp_c = -1 * (int) (0x100-scratchpad[1]) >> 1; } /* Negative temp calculation */ temp_c -= 0.25; hi_precision = (int) scratchpad[8] - (int) scratchpad[7]; hi_precision = hi_precision / (int) scratchpad[8]; temp_c = temp_c + hi_precision; } /* DS1820_FAMILY */ /* Log the temperature */ switch( log_type ) { /* Multiple Centigrade temps per line */ case 2: sprintf( temp, "\t%3.2f", temp_c ); log_string( temp ); break; /* Multiple Fahrenheit temps per line */ case 3: sprintf( temp, "\t%3.2f", c2f(temp_c) ); log_string( temp ); break; default: owSerialNum( 0, &TempSN[0], TRUE ); log_temp( sensor, temp_c, TempSN ); break; } /* switch( log_type ) */ /* Show the scratchpad if verbose is seelcted */ if( opts & OPT_VERBOSE ) { show_scratchpad( scratchpad, sensor_family ); } /* if OPT_VERBOSE */ /* Good conversion finished */ return TRUE; } else { fprintf( stderr, "CRC Failed. CRC is %02X instead of 0x00\n", lastcrc8 ); if (try == MAX_READ_TRIES - 1) { /* need to output something (0,-,NaN?) to keep columns consistent */ switch( log_type ) { /* Multiple Centigrade temps per line */ case 2: /* Multiple Fahrenheit temps per line */ case 3: sprintf( temp, "\t%3.2f", (double) 0 ); log_string( temp ); break; default: break; } /* switch( log_type ) */ } /* if tries == max_read_tries */ if( opts & OPT_VERBOSE ) { show_scratchpad( scratchpad, sensor_family ); } /* if OPT_VERBOSE */ } /* CRC 8 is OK */ } /* Scratchpad Read */ } /* owAccess failed */ } /* owAccess failed */ /* Failed to read, rest the network, delay and try again */ owTouchReset(0); msDelay( read_time ); } /* for try < 3 */ /* Failed, no good reads after MAX_READ_TRIES */ return FALSE; } /* ----------------------------------------------------------------------- Read the current counter values ----------------------------------------------------------------------- */ int read_counter( int sensor_family, int sensor ) { char temp[1024]; /* For output string */ unsigned char TempSN[8]; int page; unsigned long counter_value; if( sensor_family == DS2422_FAMILY ) { /* Read Pages 2, 3 */ for( page=2; page<=3; page++ ) { if( ReadCounter( 0, page, &counter_value ) ) { /* Log the counter */ switch( log_type ) { /* Multiple Centigrade temps per line */ case 2: case 3: sprintf( temp, "\t%ld", counter_value ); log_string( temp ); break; default: owSerialNum( 0, &TempSN[0], TRUE ); log_counter( sensor, page-2, counter_value, TempSN ); break; } /* switch( log_type ) */ } } } else if( sensor_family == DS2423_FAMILY ) { /* Read Pages 14, 15 */ for( page=14; page<=15; page++ ) { if( ReadCounter( 0, page, &counter_value ) ) { /* Log the counter */ switch( log_type ) { /* Multiple Centigrade temps per line */ case 2: case 3: sprintf( temp, "\t%ld", counter_value ); log_string( temp ); break; default: owSerialNum( 0, &TempSN[0], TRUE ); log_counter( sensor, page-14, counter_value, TempSN ); break; } /* switch( log_type ) */ } } } return FALSE; } /* ----------------------------------------------------------------------- Read the DS2406 General Purpose PIO by Tomasz R. Surmacz (tsurmacz@ict.pwr.wroc.pl) !!!! Not finished !!!! Needs an output format string system. Hard-coded for the moment. ----------------------------------------------------------------------- */ int read_ds2406( int sensor_family, int sensor ) { int pio; char temp[1024], time_format[160]; time_t mytime; if( sensor_family == DS2406_FAMILY ) { /* Read Vdd */ pio = PIO_Reading(0, 0); if (pio==-1) { printf(" PIO DS2406 sensor %d CRC failed\n", sensor); return FALSE; } mytime = time(NULL); if( mytime ) { /* Log the temperature */ switch( log_type ) { /* Multiple Centigrade temps per line */ case 2: sprintf( temp, "\t%02x,%02x", pio>>8, pio&0xff ); break; /* Multiple Fahrenheit temps per line */ case 3: sprintf( temp, "\t%02x,%02x", pio>>8, pio&0xff); break; default: sprintf( time_format, "%%b %%d %%H:%%M:%%S Sensor %d PIO: %02x,%02x, PIO-A: %s%s", sensor, pio>>8, pio&0xff, ((pio&0x1000)!=0)? // Port A latch: there was a change (((pio&0x0400)!=0)? "ON" // and the current state is ON :"on") :"off", // the current state is off, no change ((pio&0x4000)!=0)? // we have 2 ports if bit is 1 ( ((pio&0x2000)!=0)? (((pio&0x0800)!=0)? // the latch says 1 " PIO-B: ON" // and state too :" PIO-B: on") :" PIO-B: off") // the latch said no : "") ; /* Handle the time format tokens */ strftime( temp, 1024, time_format, localtime( &mytime ) ); strcat( temp, "\n" ); break; } /* switch( log_type ) */ } else { sprintf( temp, "Time Error\n" ); } /* Log it to stdout, logfile or both */ log_string( temp ); } return TRUE; } /* ----------------------------------------------------------------------- Read the DS2438 General Purpose A/D VDD Temperature ... !!!! Not finished !!!! Needs an output format string system. Hard-coded for the moment. ----------------------------------------------------------------------- */ int read_ds2438( int sensor_family, int sensor ) { double temperature; float vdd, ad; char temp[1024], time_format[160]; time_t mytime; int cad = 0; if( sensor_family == DS2438_FAMILY ) { temperature = Get_Temperature(0); /* Read Vdd */ vdd = Volt_Reading(0, 1, &cad); /* Read A/D */ ad = Volt_Reading(0, 0, NULL); mytime = time(NULL); if( mytime ) { /* Log the temperature */ switch( log_type ) { /* Multiple Centigrade temps per line */ case 2: sprintf( temp, "\t%3.2f", temperature ); break; /* Multiple Fahrenheit temps per line */ case 3: sprintf( temp, "\t%3.2f", c2f(temperature) ); break; default: sprintf( time_format, "%%b %%d %%H:%%M:%%S Sensor %d VDD: %0.2f AD: %0.2f CAD: %d C: %0.2f", sensor, vdd, ad, cad, temperature ); /* Handle the time format tokens */ strftime( temp, 1024, time_format, localtime( &mytime ) ); strcat( temp, "\n" ); break; } /* switch( log_type ) */ } else { sprintf( temp, "Time Error\n" ); } /* Log it to stdout, logfile or both */ log_string( temp ); } return FALSE; } /* ----------------------------------------------------------------------- (This routine is modified from code by Eric Wilde) Read the humidity from one sensor (e.g. the AAG TAI8540x). Log the temperature value and relative humidity. Calculated using formula cribbed from the Dallas source code (gethumd.c), DS2438 data sheet and HIH-3610 data sheet. Sensors like the TAI8540x use a DS2438 battery monitor to sense temperature and convert humidity readings from a Honeywell HIH-3610. The DS2438 scratchpad is: Status/config = scratchpad[2] Temp LSB = scratchpad[3] Temp MSB = scratchpad[4] Voltage LSB = scratchpad[5] Voltage MSB = scratchpad[6] CRC = scratchpad[10] Temp LSB temp = (Temp MSB * 32) + -------- * 0.03125 8 The temperature is a two's complement signed number. voltage = ((Voltage MSB * 256) + Voltage LSB) / 100 There are two voltages that must be read to get an accurate humidity reading. The supply voltage (VDD) is read to determine what voltage the humidity sensor is running at (this affects the zero offset and slope of the humidity curve). The sensor voltage (VAD) is read to get the humidity value. Here is the formula for the humidity (temperature and voltage compensated): ((VAD/VDD) - 0.16) * 161.29 humidity = --------------------------- 1.0546 - (0.00216 * temp) The humidity sensor is linear from approx 10% to 100% R.H. Accuracy is approx 2%. !!!! Not Finished !!!! ----------------------------------------------------------------------- */ int read_humidity( int sensor_family, int sensor ) { double temp_c; /* Converted temperature in degrees C */ float sup_voltage, /* Supply voltage in volts */ hum_voltage, /* Humidity sensor voltage in volts */ humidity; /* Calculated humidity in %RH */ unsigned char TempSN[8]; int try; for( try = 0; try < MAX_READ_TRIES; try++ ) { /* Read Vdd, the supply voltage */ if( (sup_voltage = Volt_Reading(0, 1, NULL)) != -1.0 ) { /* Read A/D reading from the humidity sensor */ if( (hum_voltage = Volt_Reading(0, 0, NULL)) != -1.0 ) { /* Read the temperature */ temp_c = Get_Temperature(0); /* Convert the measured voltage to humidity */ humidity = (((hum_voltage/sup_voltage) - 0.16) * 161.29) / (1.0546 - (0.00216 * temp_c)); if( humidity > 100.0 ) humidity = 100.0; else if( humidity < 0.0 ) humidity = 0.0; /* Log the temperature and humidity */ owSerialNum( 0, &TempSN[0], TRUE ); log_humidity( sensor, temp_c, humidity, TempSN ); /* Good conversion finished */ return TRUE; } } owTouchReset(0); msDelay(read_time); } return FALSE; } /* ----------------------------------------------------------------------- Read the DS1923 Hygrochton Temperature/Humidity Logger ----------------------------------------------------------------------- */ int read_temperature_DS1923( int sensor_family, int sensor ) { unsigned char TempSN[8], block2[2]; int try; /* Number of tries at reading device */ int b; int pre_t; float temp_c; int ival; float adval; float humidity; for( try = 0; try < MAX_READ_TRIES; try++ ) { if( owAccess(0) ) { /* Force Conversion */ if( !owWriteByte( 0, 0x55 ) || !owWriteByte( 0, 0x55 )) { return FALSE; } /* TODO CRC checking and read the addresses 020Ch to 020Fh (results)i * and the Device Sample Counter at address 0223h to 0225h. * If the count has incremented, the command was executed successfully. */ /* Sleep for conversion (spec says it takes max 666ms */ /* Q. Is it possible to poll? */ msDelay( 666 ); /* Now read the memory 0x20C:0x020F */ if( owAccess(0) ) { if( !owWriteByte( 0, 0x69 ) ) { return FALSE; } /* "Latest Temp" in the memory */ block2[0] = 0x0c; block2[1] = 0x02; /* Send the block */ if( owBlock( 0, FALSE, block2, 2 ) ) { if (block2[0] != 0x0c && block2[1] != 0x02) return FALSE; /* Send dummy password */ for(b = 0; b < 8; ++b) { owWriteByte(0, 0x04); } /* Read the temperature */ block2[0] = owReadByte(0); block2[1] = owReadByte(0); pre_t = (block2[1]/2)-41; temp_c = 1.0f * pre_t + block2[0]/512.0f; /* Read the humidity */ block2[0] = owReadByte(0); block2[1] = owReadByte(0); ival = (block2[1]*256 + block2[0])/16; adval = 1.0f * ival * 5.02f/4096; humidity = (adval-0.958f) / 0.0307f; /* Log the temperature and humidity */ /* TUTAJ masz wartosci we floatach dla Thermochrona sensor to nr sensora z pliku konfiguracyjnego, a tempsn to pewnie id urzadzenia 1wire */ owSerialNum( 0, &TempSN[0], TRUE ); log_humidity( sensor, temp_c, humidity, TempSN ); /* Good conversion finished */ return TRUE; } /* Scratchpad Read */ } /* owAccess failed */ } /* owAccess failed */ /* Failed to read, rest the network, delay and try again */ owTouchReset(0); msDelay( read_time ); } /* for try < 3 */ /* Failed, no good reads after MAX_READ_TRIES */ return FALSE; } /* ----------------------------------------------------------------------- Select the indicated device, turning on any required couplers ----------------------------------------------------------------------- */ int read_device( struct _roms *sensor_list, int sensor ) { unsigned char TempSN[8], a[3]; int s, status = 0, sensor_family; struct _coupler *c_ptr; /* Coupler linked list */ /* Tell the sensor to do a temperature conversion */ /* Sort out how to address the sensor. If sensor < num_sensors then it can be directly addressed if sensor >= num_sensors then the coupler must first be addressed and the correct branch turned on. */ if( sensor < sensor_list->max ) { /* Address the sensor directly */ owSerialNum( 0, &sensor_list->roms[sensor*8], FALSE ); } else { /* Step through the coupler list until the right sensor is found. Sensors are in order. */ s = sensor - sensor_list->max; c_ptr = coupler_top; while( c_ptr ) { if( s < c_ptr->num_main ) { /* Found the right area */ /* Is this coupler & branch already on? */ if( !cmpSN( c_ptr->SN, Last2409, 0 ) ) { /* Turn on the main branch */ if(!SetSwitch1F(0, c_ptr->SN, DIRECT_MAIN_ON, 0, a, TRUE)) { printf("Setting Switch to Main ON state failed\n"); return FALSE; } /* Remember the last selected coupler & Branch */ memcpy( &Last2409, &c_ptr->SN, 8 ); Last2409[8] = 0; } /* Select the sensor */ owSerialNum( 0, &c_ptr->main[s*8], FALSE ); break; } else { s -= c_ptr->num_main; if( s < c_ptr->num_aux ) { /* Found the right area */ /* Is this coupler & branch already on? */ if( !cmpSN( c_ptr->SN, Last2409, 1 ) ) { /* Turn on the aux branch */ if(!SetSwitch1F(0, c_ptr->SN, AUXILARY_ON, 2, a, TRUE)) { printf("Setting Switch to Aux ON state failed\n"); return FALSE; } /* Remember the last selected coupler & Branch */ memcpy( &Last2409, &c_ptr->SN, 8 ); Last2409[8] = 1; } /* Last2409 check */ /* Select the sensor */ owSerialNum( 0, &c_ptr->aux[s*8], FALSE ); break; } } s -= c_ptr->num_aux; c_ptr = c_ptr->next; } } /* Get the Serial # selected */ owSerialNum( 0, &TempSN[0], TRUE ); sensor_family = TempSN[0]; switch( sensor_family ) { case DS28EA00_FAMILY: case DS2413_FAMILY: if( (opts & OPT_DS2438) || (sensor_family==DS2413_FAMILY) ) { // read PIO status = read_pio_ds28ea00( sensor_family, sensor ); break; } // else - drop through to DS1822 case DS1820_FAMILY: case DS1822_FAMILY: case DS18B20_FAMILY: status = read_temperature( sensor_family, sensor ); // also for DS28EA00 break; case DS1923_FAMILY: status = read_temperature_DS1923( sensor_family, sensor ); break; case DS2422_FAMILY: case DS2423_FAMILY: status = read_counter( sensor_family, sensor ); break; case DS2438_FAMILY: // What type is it? { int page; for( page=3; page<8; page++) { get_ibl_type( 0, page, 0); }} if( opts & OPT_DS2438 ) { status = read_ds2438( sensor_family, sensor ); } else { status = read_humidity( sensor_family, sensor ); } break; } return status; } /* ----------------------------------------------------------------------- Read the temperaturess for all the connected sensors Step through all the sensors in the list of serial numbers ----------------------------------------------------------------------- */ int read_all( struct _roms *sensor_list ) { int x; for( x = 0; x < (num_cs+sensor_list->max); x++ ) { read_device( sensor_list, x ); } return 0; } /* ----------------------------------------------------------------------- Read a .digitemprc file from the current directory The rc file contains: TTY LOG READ_TIME