From: johanknol Date: Tue, 6 Feb 2001 20:37:48 +0000 (+0000) Subject: just an example of what SDCC can do for YOU X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=bd23417a427c80ce56efe9f2105dbb3cf64a4f4a;p=fw%2Fsdcc just an example of what SDCC can do for YOU git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@598 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- diff --git a/device/examples/ds390/ow390/Makefile b/device/examples/ds390/ow390/Makefile new file mode 100755 index 00000000..6519e97f --- /dev/null +++ b/device/examples/ds390/ow390/Makefile @@ -0,0 +1,42 @@ +#CC = sdcc +CC = /home/johan/sdcc/bin/sdcc + +MFLAGS = -mds390 --model-flat24 --stack-10bit +LFLAGS = --xram-loc 0x180080 --code-loc 0x10000 -Wl-r + +TARGETS = tstfind.hex temp.hex swtloop.hex swtoper.hex counter.hex \ + tstow.hex thermodl.hex + +OW_OBJECTS = ownetu.rel owsesu.rel owllu.rel owlli.rel owtrnu.rel \ + crcutil.rel tinilnk.rel findtype.rel ds2480ut.rel owfile.rel + +SENSOR_OBJECTS = temp10.rel swt12.rel cnt1d.rel thermo21.rel + +TINI_TEST_OBJECTS = time.rel + +all: ow.lib sensors.lib $(TINI_TEST_OBJECTS) $(TARGETS) + +ow.lib: $(OW_OBJECTS) + rm -f $@; \ + for object in $(OW_OBJECTS) $(TINI_TEST_OBJECTS); do \ + echo $$object >>$@; \ + done; + +sensors.lib: $(SENSOR_OBJECTS) + rm -f $@; \ + for object in $(SENSOR_OBJECTS); do \ + echo $$object >>$@; \ + done; + +clean: + rm -f core *~ \#* *.asm *.cdb *.rel *.hex *.ihx *.lst *.map \ + *.rst *.sym *.lnk *.lib + +%.hex: ow.lib sensors.lib $(TINI_TEST_OBJECTS) %.rel + $(CC) $(MFLAGS) $(LFLAGS) $*.rel $(TINI_TEST_OBJECTS) \ + -L . ow.lib sensors.lib + packihx $*.ihx >$@ + #tinitalk -c execute $@ + +%.rel: %.c + $(CC) -c $(MFLAGS) $< diff --git a/device/examples/ds390/ow390/cnt1d.c b/device/examples/ds390/ow390/cnt1d.c new file mode 100644 index 00000000..cdf66fdd --- /dev/null +++ b/device/examples/ds390/ow390/cnt1d.c @@ -0,0 +1,104 @@ +//--------------------------------------------------------------------------- +// 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" +#include "cnt1d.h" + +//---------------------------------------------------------------------- +// 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 +// +int ReadCounter(int portnum, uchar SerialNum[8], int CounterPage, + unsigned long *Count) +{ + int rt=FALSE; + uchar send_block[30]; + int send_cnt=0, address, i; + ushort lastcrc16; + + setcrc16(portnum,0); + + // set the device serial number to the counter device + 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; +} diff --git a/device/examples/ds390/ow390/cnt1d.h b/device/examples/ds390/ow390/cnt1d.h new file mode 100755 index 00000000..2750069c --- /dev/null +++ b/device/examples/ds390/ow390/cnt1d.h @@ -0,0 +1 @@ +extern int ReadCounter(int, uchar *SerialNum, int, unsigned long *); diff --git a/device/examples/ds390/ow390/counter.c b/device/examples/ds390/ow390/counter.c new file mode 100755 index 00000000..89e6eebc --- /dev/null +++ b/device/examples/ds390/ow390/counter.c @@ -0,0 +1,155 @@ +//--------------------------------------------------------------------------- +// 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. +//--------------------------------------------------------------------------- +// +// counter.c - Application to read the 1-Wire Net DS2423 - counter. +// +// This application uses the files from the 'Public Domain' +// 1-Wire Net libraries ('general' and 'userial'). +// +// Version: 2.00 +// + +#include +#include +#include "ownet.h" +#include "cnt1d.h" + +// defines +#define MAXDEVICES 20 + +// local functions +void PrintSerialNum(uchar *SerialNum); + +// local serial numbers +static uchar FamilySN[MAXDEVICES][8]; + +// tini hack +int argc=2; +char *argv[]={__FILE__, "exow"}; + +//---------------------------------------------------------------------- +// Main Test for the DS2423 - counter +// +int main() //short argc, char **argv) +{ + char return_msg[128]; + int NumDevices=0; + int i; + int CounterPage; + ulong Count; + int portnum=0; + + //------------------------------------------------------ + // Introduction header + printf("\n/---------------------------------------------\n"); + printf(" Counter Application - V2.00\n" + " The following is a test to excersize a\n" + " DS2423 - counter \n\n"); + + printf(" Press any CTRL-C to stop this program.\n\n"); + printf(" Output [Serial Number(s) ... Counter Value ... Counter Value ... " + "Counter Value ... Counter Value] \n\n"); + + // check for required port name + if (argc != 2) + { + printf("1-Wire Net name required on command line!\n" + " (example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" " + "(Linux DS2480),\"1\" (Win32 TMEX)\n"); + exit(1); + } + + // attempt to acquire the 1-Wire Net + if (!owAcquire(portnum, argv[1], return_msg)) + { + printf("%s",return_msg); + exit(1); + } + + // success + printf("%s",return_msg); + + // Find the device(s) + NumDevices = FindDevices(portnum, &FamilySN[0], 0x1D, MAXDEVICES); + if (NumDevices>0) + { + printf("\n"); + printf("Device(s) Found: \n"); + for (i = 0; i < NumDevices; i++) + { + PrintSerialNum(FamilySN[i]); + printf("\n"); + } + printf("\n\n"); + + // (stops on CTRL-C) + do + { + // read the current counters + for (i = 0; i < NumDevices; i++) + { + printf("\n"); + PrintSerialNum(FamilySN[i]); + + for (CounterPage = 12; CounterPage <= 15; CounterPage++) + { + if (ReadCounter(portnum, FamilySN[i], CounterPage, &Count)) + { + printf(" %10ld ", Count); + } + else + printf("\nError reading counter, verify device present:%d\n", + owVerify(portnum,FALSE)); + } + } + printf("\n\n"); + } + while (!key_abort()); + } + else + printf("\n\n\n ERROR, device not found!\n"); + + // release the 1-Wire Net + owRelease(portnum,return_msg); + printf("%s",return_msg); + exit(0); + + return 0; +} + +// ------------------------------------------------------------------------------- +// Read and print the serial number +// +void PrintSerialNum(uchar *SerialNum) +{ + int i; + + for (i = 7; i>=0; i--) + printf("%02X", SerialNum[i]); +} + + + diff --git a/device/examples/ds390/ow390/crcutil.c b/device/examples/ds390/ow390/crcutil.c new file mode 100644 index 00000000..09add308 --- /dev/null +++ b/device/examples/ds390/ow390/crcutil.c @@ -0,0 +1,122 @@ +//--------------------------------------------------------------------------- +// 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 + +// tinihack, data is a reserved keyword for sdcc. So: +#define data DaTa + +// Include files +#include "ownet.h" + +// Local global variables +static ushort utilcrc16[MAX_PORTNUM]; +static 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 shorteger. 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 data) +{ + data = (data ^ (utilcrc16[portnum] & 0xff)) & 0xff; + utilcrc16[portnum] >>= 8; + + if (oddparity[data & 0xf] ^ oddparity[data >> 4]) + utilcrc16[portnum] ^= 0xc001; + + data <<= 6; + utilcrc16[portnum] ^= data; + data <<= 1; + utilcrc16[portnum] ^= data; + + 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]; +} diff --git a/device/examples/ds390/ow390/ds2480.h b/device/examples/ds390/ow390/ds2480.h new file mode 100755 index 00000000..12ab46eb --- /dev/null +++ b/device/examples/ds390/ow390/ds2480.h @@ -0,0 +1,187 @@ +//--------------------------------------------------------------------------- +// 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 DS2480 constants +// +// Version: 2.00 +// +// History: 1.02 -> 1.03 Make sure uchar is not defined twice. +// +// + +// Mode Commands +#define MODE_DATA 0xE1 +#define MODE_COMMAND 0xE3 +#define MODE_STOP_PULSE 0xF1 + +// Return byte value +#define RB_CHIPID_MASK 0x1C +#define RB_RESET_MASK 0x03 +#define RB_1WIRESHORT 0x00 +#define RB_PRESENCE 0x01 +#define RB_ALARMPRESENCE 0x02 +#define RB_NOPRESENCE 0x03 + +#define RB_BIT_MASK 0x03 +#define RB_BIT_ONE 0x03 +#define RB_BIT_ZERO 0x00 + +// Masks for all bit ranges +#define CMD_MASK 0x80 +#define FUNCTSEL_MASK 0x60 +#define BITPOL_MASK 0x10 +#define SPEEDSEL_MASK 0x0C +#define MODSEL_MASK 0x02 +#define PARMSEL_MASK 0x70 +#define PARMSET_MASK 0x0E + +// Command or config bit +#define CMD_COMM 0x81 +#define CMD_CONFIG 0x01 + +// Function select bits +#define FUNCTSEL_BIT 0x00 +#define FUNCTSEL_SEARCHON 0x30 +#define FUNCTSEL_SEARCHOFF 0x20 +#define FUNCTSEL_RESET 0x40 +#define FUNCTSEL_CHMOD 0x60 + +// Bit polarity/Pulse voltage bits +#define BITPOL_ONE 0x10 +#define BITPOL_ZERO 0x00 +#define BITPOL_5V 0x00 +#define BITPOL_12V 0x10 + +// One Wire speed bits +#define SPEEDSEL_STD 0x00 +#define SPEEDSEL_FLEX 0x04 +#define SPEEDSEL_OD 0x08 +#define SPEEDSEL_PULSE 0x0C + +// Data/Command mode select bits +#define MODSEL_DATA 0x00 +#define MODSEL_COMMAND 0x02 + +// 5V Follow Pulse select bits (If 5V pulse +// will be following the next byte or bit.) +#define PRIME5V_TRUE 0x02 +#define PRIME5V_FALSE 0x00 + +// Parameter select bits +#define PARMSEL_PARMREAD 0x00 +#define PARMSEL_SLEW 0x10 +#define PARMSEL_12VPULSE 0x20 +#define PARMSEL_5VPULSE 0x30 +#define PARMSEL_WRITE1LOW 0x40 +#define PARMSEL_SAMPLEOFFSET 0x50 +#define PARMSEL_ACTIVEPULLUPTIME 0x60 +#define PARMSEL_BAUDRATE 0x70 + +// Pull down slew rate. +#define PARMSET_Slew15Vus 0x00 +#define PARMSET_Slew2p2Vus 0x02 +#define PARMSET_Slew1p65Vus 0x04 +#define PARMSET_Slew1p37Vus 0x06 +#define PARMSET_Slew1p1Vus 0x08 +#define PARMSET_Slew0p83Vus 0x0A +#define PARMSET_Slew0p7Vus 0x0C +#define PARMSET_Slew0p55Vus 0x0E + +// 12V programming pulse time table +#define PARMSET_32us 0x00 +#define PARMSET_64us 0x02 +#define PARMSET_128us 0x04 +#define PARMSET_256us 0x06 +#define PARMSET_512us 0x08 +#define PARMSET_1024us 0x0A +#define PARMSET_2048us 0x0C +#define PARMSET_infinite 0x0E + +// 5V strong pull up pulse time table +#define PARMSET_16p4ms 0x00 +#define PARMSET_65p5ms 0x02 +#define PARMSET_131ms 0x04 +#define PARMSET_262ms 0x06 +#define PARMSET_524ms 0x08 +#define PARMSET_1p05s 0x0A +#define PARMSET_2p10s 0x0C +#define PARMSET_infinite 0x0E + +// Write 1 low time +#define PARMSET_Write8us 0x00 +#define PARMSET_Write9us 0x02 +#define PARMSET_Write10us 0x04 +#define PARMSET_Write11us 0x06 +#define PARMSET_Write12us 0x08 +#define PARMSET_Write13us 0x0A +#define PARMSET_Write14us 0x0C +#define PARMSET_Write15us 0x0E + +// Data sample offset and Write 0 recovery time +#define PARMSET_SampOff3us 0x00 +#define PARMSET_SampOff4us 0x02 +#define PARMSET_SampOff5us 0x04 +#define PARMSET_SampOff6us 0x06 +#define PARMSET_SampOff7us 0x08 +#define PARMSET_SampOff8us 0x0A +#define PARMSET_SampOff9us 0x0C +#define PARMSET_SampOff10us 0x0E + +// Active pull up on time +#define PARMSET_PullUp0p0us 0x00 +#define PARMSET_PullUp0p5us 0x02 +#define PARMSET_PullUp1p0us 0x04 +#define PARMSET_PullUp1p5us 0x06 +#define PARMSET_PullUp2p0us 0x08 +#define PARMSET_PullUp2p5us 0x0A +#define PARMSET_PullUp3p0us 0x0C +#define PARMSET_PullUp3p5us 0x0E + +// Baud rate bits +#define PARMSET_9600 0x00 +#define PARMSET_19200 0x02 +#define PARMSET_57600 0x04 +#define PARMSET_115200 0x06 + +// DS2480 program voltage available +#define DS2480PROG_MASK 0x20 + +// mode bit flags +#define MODE_NORMAL 0x00 +#define MODE_OVERDRIVE 0x01 +#define MODE_STRONG5 0x02 +#define MODE_PROGRAM 0x04 +#define MODE_BREAK 0x08 + +extern int DS2480Detect(int); +extern int DS2480ChangeBaud(int, uchar); + +// global DS2480 state +extern int ULevel[MAX_PORTNUM]; // current DS2480 1-Wire Net level +extern int UBaud[MAX_PORTNUM]; // current DS2480 baud rate +extern int UMode[MAX_PORTNUM]; // current DS2480 command or data mode state +extern int USpeed[MAX_PORTNUM]; // current DS2480 1-Wire Net comm speed + diff --git a/device/examples/ds390/ow390/ds2480ut.c b/device/examples/ds390/ow390/ds2480ut.c new file mode 100755 index 00000000..0e01b3f1 --- /dev/null +++ b/device/examples/ds390/ow390/ds2480ut.c @@ -0,0 +1,200 @@ +//--------------------------------------------------------------------------- +// 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 - DS2480 utility functions. +// +// Version: 2.00 +// +// 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. + +#include "ownet.h" +#include "ds2480.h" + +// global DS2480 state +int ULevel[MAX_PORTNUM]; // current DS2480 1-Wire Net level +int UBaud[MAX_PORTNUM]; // current DS2480 baud rate +int UMode[MAX_PORTNUM]; // current DS2480 command or data mode state +int USpeed[MAX_PORTNUM]; // current DS2480 1-Wire Net communication speed + +//--------------------------------------------------------------------------- +// Attempt to resyc and detect a DS2480 +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// +// Returns: TRUE - DS2480 detected successfully +// FALSE - Could not detect DS2480 +// +int DS2480Detect(int portnum) +{ + uchar sendpacket[10],readbuffer[10]; + short sendlen=0; + short rt=FALSE; + + // reset modes + ULevel[portnum] = MODE_NORMAL; + 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) + return FALSE; + + // set the FLEX configuration parameters + // default PDSRC = 1.37Vus + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_SLEW | PARMSET_Slew1p37Vus; + // default W1LT = 8us + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_WRITE1LOW | PARMSET_Write8us; + // default DSO/WORT = 10us + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_SAMPLEOFFSET | PARMSET_SampOff10us; + + // construct the command to read the baud rate (to test command block) + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_PARMREAD | (PARMSEL_BAUDRATE >> 3); + + // also do 1 bit operation (to test 1-Wire block) + sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_BIT | UBaud[portnum] | BITPOL_ONE; + + // 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])) + return TRUE; + } + } + + return FALSE; +} + +//--------------------------------------------------------------------------- +// Change the DS2480 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 DS2480 baud rate. +// +int DS2480ChangeBaud(int portnum, uchar newbaud) +{ + int rt=FALSE; + uchar readbuffer[5],sendpacket[5],sendpacket2[5]; + int sendlen=0,sendlen2=0; + + // see if diffenent then current baud rate + if (UBaud[portnum] == newbaud) + return TRUE; + 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)) + 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; + } + } + } + } + + // if lost communication with DS2480 then reset + if (rt != TRUE) + DS2480Detect(portnum); + + return UBaud[portnum]; +} diff --git a/device/examples/ds390/ow390/findtype.c b/device/examples/ds390/ow390/findtype.c new file mode 100644 index 00000000..5fc2a913 --- /dev/null +++ b/device/examples/ds390/ow390/findtype.c @@ -0,0 +1,71 @@ +//--------------------------------------------------------------------------- +// 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. +//--------------------------------------------------------------------------- +// +// findtype.c - Test module to find all devices of one type. +// +// Version: 2.00 +// +//---------------------------------------------------------------------- +// +// +#include "ownet.h" + +//---------------------------------------------------------------------- +// Search for devices +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// +// Returns: TRUE(1) success, device type found +// FALSE(0) device not found +// +int FindDevices(int portnum, uchar FamilySN[][8], int family_code, int MAXDEVICES) +{ + int NumDevices=0; + int TotalDevices=0; + + // find the devices + // set the search to first find that family code + owFamilySearchSetup(portnum,family_code); + + // loop to find all of the devices up to MAXDEVICES + NumDevices = 0; + do + { + // perform the search + if (!owNext(portnum,TRUE, FALSE)) + break; + owSerialNum(portnum,FamilySN[NumDevices], TRUE); + if (FamilySN[NumDevices][0] == family_code) + { + NumDevices++; + } + } + while (NumDevices < (MAXDEVICES - 1)); + + // check if not at least 1 device + return NumDevices; +} diff --git a/device/examples/ds390/ow390/owfile.c b/device/examples/ds390/ow390/owfile.c new file mode 100644 index 00000000..6ad8f9fb --- /dev/null +++ b/device/examples/ds390/ow390/owfile.c @@ -0,0 +1,270 @@ +//--------------------------------------------------------------------------- +// 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. +//--------------------------------------------------------------------------- +// +// owFile.C: Rudimentary level functions for reading and writing TMEX +// files on NVRAM iButton using the packet level functions. +// +// Version: 2.00 +// +// 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. +// + +#include "ownet.h" + +//-------------------------------------------------------------------------- +// Read a TMEX file return it in the provided buffer. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'filename' - pointer to five byte filename to read where the +// the first four bytes are the name and the fifth is +// the extension (0 to 101 decimal). +// 'buf' - pointer to a buffer to place the file information into. +// This may need to be as large as 7084 bytes. +// +// Supported devices: All devices supported by owReadPacketStd +// +// Returns: >=0 success, number of bytes in the buffer +// <0 failed to read the file (error code) +// +int owReadFile(int portnum, uchar *filename, uchar *buf) +{ + uchar dirpg=0,pgbuf[32],filepg=0,pglen; + short bufcnt=0,i; + + // loop read directory pages until the file entry is found + do + { + // read a directory page + pglen = owReadPacketStd(portnum,TRUE,dirpg,pgbuf); + + // check for reading error + if (pglen <= 0) + return READ_ERROR; + + // if this is the first page make sure this is a directory + // structure + if ( ((dirpg == 0) && + ((pgbuf[0] != 0xAA) || (pgbuf[1] != 0) || (pglen < 7))) + || + ((pglen-1) % 7) ) + return INVALID_DIR; + + // loop through each file entry in directory page (page 0 exception) + for (i = (dirpg == 0) ? 7 : 0; i < 28; i += 7) + { + // file entry found? + if ((filename[0] == pgbuf[i]) && + (filename[1] == pgbuf[i+1]) && + (filename[2] == pgbuf[i+2]) && + (filename[3] == pgbuf[i+3]) && + (filename[4] == (pgbuf[i+4] & 0x7F)) ) + { + // get the file starting page number + filepg = pgbuf[i+5]; + break; + } + } + + // get the next directory page (from page pointer) + dirpg = pgbuf[pglen-1]; + } + while (dirpg && (filepg == 0)); + + // check if file found + if (!filepg) + return NO_FILE; + + // loop to read the file pages + do + { + // read a file page + pglen = owReadPacketStd(portnum,TRUE,filepg,pgbuf); + + // check result of read + if (pglen <= 0) + return READ_ERROR; + + // append the page data to the buffer + for (i = 0; i < (pglen - 1); i++) + buf[bufcnt++] = pgbuf[i]; + + // get the next file page (from page pointer) + filepg = pgbuf[pglen-1]; + } + while (filepg); + + // return the number of data bytes read + return bufcnt; +} + + +//-------------------------------------------------------------------------- +// Format and Write a TMEX file. +// Any previous files will be removed in the Format operation. +// The file length 'fllen' can be up to: +// 420 bytes for a DS1993 +// 1736 bytes for a DS1995 +// 7084 bytes for a DS1996. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'filename' - pointer to five byte filename to write where the +// the first four bytes are the name and the fifth is +// the extension (0 to 101 decimal). +// 'buf' - pointer to a buffer containing the file information to write. +// +// Supported devices: DS1993, DS1994, DS1995, DS1996 +// +// Returns: TRUE(1) success, device formated and file written +// <0 failed to read the file (error code) +// +// +int owFormatWriteFile(int portnum, uchar *filename, int fllen, uchar *buf) +{ + uchar dummydir[] = { 0xAA, 0, 0x80, 0x01, 0, 0, 0, 0 }, + newdir[] = { 0xAA, 0, 0x80, 0x01, 0, 0, 0, ' ', ' ', ' ', ' ', 0, 1, 1, 0 }, + bmpg1[] = { 0x03,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x02 }, + bmpg2[] = { 0,0,0,0,0 }, pgbuf[32]; + int i,numdirpgs,flpg,bmpg1len,bmpg2len,cntleft,pos,numpgs; + + // calculate the number of pages needed to write the file + numpgs = (fllen / 28) + ((fllen % 28) ? 1 : 0); + + // put the file in the newdirectory + for(i = 0; i < 5; i++) + newdir[i+7] = filename[i]; + newdir[13] = (uchar)numpgs; + + // set the directory pages for formatting device depending on the device type + switch (SerialNum[portnum][0]) //jpe + { + case 0x06: // DS1993 + // check for file too big + if (numpgs > 15) + return FILE_TOO_BIG; + // set the bitmap in the directory page + for (i = 0; i < numpgs; i++) + bitacc(WRITE_FUNCTION,1,i+1,&newdir[3]); + numdirpgs = 1; + flpg = 1; + newdir[12] = (uchar)flpg; + break; + case 0x0A: // DS1995 + // check for file too big + if (numpgs > 62) + return FILE_TOO_BIG; + // set to external bitmap file + newdir[2] = 0; + // set the bitmap in the first (and only) bitmap page + for (i = 0; i < numpgs; i++) + bitacc(WRITE_FUNCTION,1,i+2,&bmpg1[0]); + numdirpgs = 2; + flpg = 2; + newdir[12] = (uchar)flpg; // startpage + bmpg1len = 9; + newdir[3] = 0; // remove local bitmap + newdir[5] = 1; // bitmap start page + newdir[6] = 1; // bitmap number of pages + break; + case 0x0C: // DS1996 + // check for file too big + if (numpgs > 253) + return FILE_TOO_BIG; + // set to external bitmap file + newdir[2] = 0; + // set the 3rd bitmap page in the bitmap + bitacc(WRITE_FUNCTION,1,2,&bmpg1[0]); + + // set the bitmap in the first and second bitmap page + for (i = 0; i < numpgs; i++) + { + if (i <= 221) + bitacc(WRITE_FUNCTION,1,i+3,&bmpg1[0]); + else + bitacc(WRITE_FUNCTION,1,i-221,&bmpg2[0]); + } + numdirpgs = 3; + flpg = 3; + newdir[12] = (uchar)flpg; // startpage + bmpg1len = 29; + bmpg2len = 5; + newdir[3] = 0; // remove local bitmap + newdir[5] = 1; // bitmap start page + newdir[6] = 2; // bitmap number of pages + break; + default: + return WRONG_TYPE; + } + + // write a dummy directory in page 0 in case we get interrupted + if (!owWritePacketStd(portnum,0,dummydir,8,FALSE,FALSE)) + return WRITE_ERROR; + + // loop to write the file in contiguous pages start with flpg + cntleft = fllen; // count of bytes left to write + pos = 0; // current position in the buffer to write + while (cntleft > 0) + { + // get a page of data to write + for (i = 0; i < ((cntleft > 28) ? 28 : cntleft); i++) + pgbuf[i] = buf[pos++]; + + // adjust the bytes left + cntleft -= i; + + // set the next page pointer + pgbuf[i] = (cntleft == 0) ? 0 : flpg+1; + + // write the page and check to result + if (!owWritePacketStd(portnum,flpg,pgbuf,i+1,FALSE,FALSE)) + return WRITE_ERROR; + + // set the next page + flpg++; + } + + // now write the second bitmap page if needed + if (numdirpgs == 3) + if (!owWritePacketStd(portnum,2,bmpg2,bmpg2len,FALSE,FALSE)) + return WRITE_ERROR; + + // now write the first bitmap page if needed + if (numdirpgs >= 2) + if (!owWritePacketStd(portnum,1,bmpg1,bmpg1len,FALSE,FALSE)) + return WRITE_ERROR; + + // now write the directory page + if (!owWritePacketStd(portnum,0,newdir,15,FALSE,FALSE)) + return WRITE_ERROR; + + // success file written + return TRUE; +} + diff --git a/device/examples/ds390/ow390/owlli.c b/device/examples/ds390/ow390/owlli.c new file mode 100644 index 00000000..314a0c5d --- /dev/null +++ b/device/examples/ds390/ow390/owlli.c @@ -0,0 +1,430 @@ +//--------------------------------------------------------------------------- +// 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. +//--------------------------------------------------------------------------- +// +// iow.c +// +// Minimal access routines for TINI internal one-wire bus patched together +// from Dallas example code (hence the copyright notice above). +// +// Kevin Vigor, 11/20/2000 + +#include +#include "ownet.h" + +/* The internal 1-wire bus is hooked to P3.5, a.k.a T1 */ +/* The "activity" LED is also hooked to this line. */ +#define INT_OW_PORT T1 + +// local variables for this module to hold search state information +static int LastDiscrepancy; +static int LastFamilyDiscrepancy; +static int LastDevice; +static unsigned char iSerialNum[8]; + +static uchar iowTouchBit(uchar); +static uchar iowTouchByte(uchar); + +//-------------------------------------------------------------------------- +// Reset all of the devices on the 1-Wire Net and return the result. +// +// Returns: TRUE(1): presense pulse(s) detected, device(s) reset +// FALSE(0): no presense pulses detected +// +unsigned char iowTouchReset(void) +{ + unsigned char result; + + //printf ("iowTouchReset(): "); + + /* Code stolen straight from appnote 126. */ + INT_OW_PORT = 0; /* drive bus low. */ + ClockMicroSecondsDelay(480); + INT_OW_PORT = 1; /* bus high. */ + ClockMicroSecondsDelay(120); + result = INT_OW_PORT; /* get presence detect pulse. */ + ClockMicroSecondsDelay(360); + + //printf ("%d\n", result); + return result; +} + +//-------------------------------------------------------------------------- +// 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. +// +// Returns: 0: 0 bit read from sendbit +// 1: 1 bit read from sendbit +// +static unsigned char iowTouchBit(unsigned char sendbit) +{ + unsigned char result; + + INT_OW_PORT = 0; /* start timeslot. */ + ClockMicroSecondsDelay(1); + + INT_OW_PORT = sendbit; /* send bit out. */ + ClockMicroSecondsDelay(9); + result = INT_OW_PORT; /* sample result @ 10 us. */ + ClockMicroSecondsDelay(50); + INT_OW_PORT = 1; /* timeslot done. */ + ClockMicroSecondsDelay(5); + + return result; +} + +//-------------------------------------------------------------------------- +// 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. +// +// 'sendbyte' - 8 bits to send (least significant byte) +// +// Returns: 8 bytes read from sendbyte +// +static unsigned char iowTouchByte(unsigned char sendbyte) +{ + unsigned char i; + unsigned char result = 0; + + //printf ("iowTouchByte(%02x): ", sendbyte); + + for (i = 0; i < 8; i++) + { + result |= (iowTouchBit(sendbyte & 1) << i); + sendbyte >>= 1; + } + + //printf ("%02x\n", result); + return result; +} + +//-------------------------------------------------------------------------- +// 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. +// +// 'sendbyte' - 8 bits to send (least significant byte) +// +// Returns: TRUE: bytes written and echo was the same +// FALSE: echo was not the same +// +unsigned char iowWriteByte(unsigned char sendbyte) +{ + return (iowTouchByte(sendbyte) == sendbyte) ? TRUE : FALSE; +} + +//-------------------------------------------------------------------------- +// 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 64 +// +unsigned char iowBlock(unsigned char do_reset, + unsigned char *tran_buf, + unsigned char tran_len) +{ + int i; + + // check for a block too big + if (tran_len > 64) + return FALSE; + + // check if need to do a owTouchReset first + if (do_reset) + { + if (!iowTouchReset()) + return FALSE; + } + + // send and receive the buffer + for (i = 0; i < tran_len; i++) + tran_buf[i] = iowTouchByte(tran_buf[i]); + + return TRUE; +} + +//-------------------------------------------------------------------------- +// Send 8 bits of read communication to the 1-Wire Net and and return the +// result 8 bits read from the 1-Wire Net. +// +// Returns: 8 bytes read from 1-Wire Net +// +unsigned char iowReadByte(void) +{ + return iowTouchByte(0xFF); +} + +//-------------------------------------------------------------------------- +// 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. +// +// 'do_reset' - TRUE (1) +// 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 iSerialNum[portnum] +// FALSE (0): There are no devices on the 1-Wire Net. +// +unsigned char iowFirst(unsigned char do_reset, unsigned char alarm_only) +{ + // reset the search state + LastDiscrepancy = 0; + LastDevice = FALSE; + LastFamilyDiscrepancy = 0; + + return iowNext(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. +// +// '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 iSerialNum[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. +// +unsigned char iowNext(unsigned char do_reset, unsigned char alarm_only) +{ + int bit_test, search_direction, bit_number; + int last_zero, serial_byte_number, next_result; + unsigned char serial_byte_mask; + unsigned char lastcrc8; + + //printf ("iowNext(%d,%d)\n", do_reset, alarm_only); + + // initialize for search + bit_number = 1; + last_zero = 0; + serial_byte_number = 0; + serial_byte_mask = 1; + next_result = 0; + lastcrc8 = 0; + + // if the last call was not the last one + if (!LastDevice) + { + // check if reset first is requested + if (do_reset) + { + // reset the 1-wire + // if there are no parts on 1-wire, return FALSE + if (!iowTouchReset()) + { + // reset the search + LastDiscrepancy = 0; + LastFamilyDiscrepancy = 0; + return FALSE; + } + } + + // If finding alarming devices issue a different command + if (alarm_only) + iowWriteByte(0xEC); // issue the alarming search command + else + iowWriteByte(0xF0); // issue the search command + + // loop to do the search + do + { + // read a bit and its compliment + bit_test = iowTouchBit(1) << 1; + bit_test |= iowTouchBit(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) + search_direction = ((iSerialNum[serial_byte_number] & serial_byte_mask) > 0); + else + // if equal to last pick 1, if not then pick 0 + search_direction = (bit_number == LastDiscrepancy); + + // 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 = last_zero; + } + + // set or clear the bit in the iSerialNum byte serial_byte_number + // with mask serial_byte_mask + if (search_direction == 1) + iSerialNum[serial_byte_number] |= serial_byte_mask; + else + iSerialNum[serial_byte_number] &= ~serial_byte_mask; + + // serial number search direction write bit + iowTouchBit(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 iSerialNum byte serial_byte_number + // and reset mask + if (serial_byte_mask == 0) + { + lastcrc8 = docrc8(lastcrc8,iSerialNum[serial_byte_number]); // accumulate the CRC + serial_byte_number++; + serial_byte_mask = 1; + } + } + } + while(serial_byte_number < 8); // loop until through all iSerialNum bytes 0-7 + + // if the search was successful then + if (!((bit_number < 65) || lastcrc8)) + { + // search successful so set LastDiscrepancy,LastDevice,next_result + LastDiscrepancy = last_zero; + LastDevice = (LastDiscrepancy == 0); + next_result = TRUE; + } + } + + // if no device found then reset counters so next 'next' will be + // like a first + if (!next_result || !iSerialNum[0]) + { + LastDiscrepancy = 0; + LastDevice = FALSE; + LastFamilyDiscrepancy = 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. +// +// '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 iowSerialNum(unsigned char *serialnum_buf, unsigned char do_read) +{ + int i; + + // read the internal buffer and place in 'serialnum_buf' + if (do_read) + { + for (i = 0; i < 8; i++) + { + serialnum_buf[i] = iSerialNum[i]; + } + } + // set the internal buffer from the data in 'serialnum_buf' + else + { + for (i = 0; i < 8; i++) + { + iSerialNum[i] = serialnum_buf[i]; + } + } +} + +// unsupported routines + +uchar iowSpeed(int speed) { + speed; // hush the compiler + printf ("No owSpeed for internal ow yet\n"); + return FALSE; +} + +uchar iowLevel(int level) { + level; // hush the compiler + printf ("No owLevel for internal ow yet\n"); + return FALSE; +} + +uchar iowProgramPulse() { + printf ("No owProgramPulse for internal ow yet\n"); + return FALSE; +} diff --git a/device/examples/ds390/ow390/owllu.c b/device/examples/ds390/ow390/owllu.c new file mode 100755 index 00000000..4030cf1a --- /dev/null +++ b/device/examples/ds390/ow390/owllu.c @@ -0,0 +1,486 @@ +//--------------------------------------------------------------------------- +// 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.00 +// +// 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. + +#include "ownet.h" +#include "ds2480.h" + +// local varable flag, true if program voltage available +static int 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. +// +int owTouchReset(int portnum) +{ + uchar readbuffer[10],sendpacket[10]; + int 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 + return FALSE; + } + } + + // 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 +// +int owTouchBit(int portnum, int sendbit) +{ + uchar readbuffer[10],sendpacket[10]; + int 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; + } + } + + // 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 +// +int owWriteByte(int portnum, int 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 was provided to +// OpenCOM to indicate the port number. +// +// Returns: 8 bytes read from 1-Wire Net +// +int owReadByte(int portnum) +{ + return owTouchByte(portnum,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 bytes read from sendbyte +// +int owTouchByte(int portnum, int sendbyte) +{ + uchar readbuffer[10],sendpacket[10]; + int 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 == 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]; + } + } + + // 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 +// +int owSpeed(int portnum, int new_speed) +{ + uchar sendpacket[5]; + short sendlen=0; + int 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)) + { + 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 +// +int owLevel(int portnum, int new_level) +{ + uchar sendpacket[10],readbuffer[10]; + short sendlen=0; + short 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)) + { + // 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; + } + } + } + } + // 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; + } + } + } + } + + // 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 +// +int owProgramPulse(int portnum) +{ + uchar sendpacket[10],readbuffer[10]; + short 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; + } + } + + // an error occured so re-sync with DS2480 + DS2480Detect(portnum); + + return FALSE; +} diff --git a/device/examples/ds390/ow390/ownet.h b/device/examples/ds390/ow390/ownet.h new file mode 100755 index 00000000..96b4ef02 --- /dev/null +++ b/device/examples/ds390/ow390/ownet.h @@ -0,0 +1,151 @@ +//--------------------------------------------------------------------------- +// 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.00 +// +// History: 1.02 -> 1.03 Make sure uchar is not defined twice. +// 1.03 -> 2.00 Changed 'MLan' to 'ow'. +// + +// Typedefs +#ifndef OW_UCHAR +#define OW_UCHAR + typedef unsigned char uchar; + typedef unsigned int ushort; + typedef unsigned long ulong; +#endif + +// general defines +#define WRITE_FUNCTION 1 +#define READ_FUNCTION 0 + +// error codes +#define READ_ERROR -1 +#define INVALID_DIR -2 +#define NO_FILE -3 +#define WRITE_ERROR -4 +#define WRONG_TYPE -5 +#define FILE_TOO_BIG -6 + +// Misc +#define FALSE 0 +#define TRUE 1 +#define MAX_PORTNUM 16 + +// mode bit flags +#define MODE_NORMAL 0x00 +#define MODE_OVERDRIVE 0x01 +#define MODE_STRONG5 0x02 +#define MODE_PROGRAM 0x04 +#define MODE_BREAK 0x08 + +// family codes of devices +#define DIR_FAMILY 0x01 +#define TEMP_FAMILY 0x10 +#define SWITCH_FAMILY 0x12 +#define COUNT_FAMILY 0x1D +#define ATOD_FAMILY 0X20 +#define THERMO_FAM 0x21 +// this is weird, the DS2502 should be 0x09 +#define DS2502_FAMILY 0x89 + +// tinilnk.c +extern void FlushCOM(int); +extern int WriteCOM(int,int,uchar*); +extern int ReadCOM(int,int,uchar*); +extern void BreakCOM(int); +extern void SetBaudCOM(int,int); +extern void msDelay(int); +extern long msGettick(void); +extern int OpenCOM(int,char *); +extern void CloseCOM(int); + +// ownetu.c +extern int owFirst(int,int,int); +extern int owNext(int,int,int); +extern void owSerialNum(int,uchar *, int); +extern void owFamilySearchSetup(int,int); +extern void owSkipFamily(int); +extern int owAccess(int); +extern int owVerify(int,int); +extern int owOverdriveAccess(int); +extern int bitacc(int,int,int,uchar *); +extern uchar SerialNum[MAX_PORTNUM][8]; + +// owtrnu.c +extern int owBlock(int,int,uchar *,int); +extern int owReadPacketStd(int,int,int,uchar *); +extern int owWritePacketStd(int,int,uchar *,int,int,int); +extern int owProgramByte(int,int,int,int,int,int); + +// crcutil.c +extern void setcrc16(int,ushort); +extern ushort docrc16(int,ushort); +extern void setcrc8(int,uchar); +extern uchar docrc8(int,uchar); + +// owllu.c +extern int owTouchReset(int); +extern int owTouchByte(int, int); +extern int owWriteByte(int,int); +extern int owReadByte(int); +extern int owSpeed(int,int); +extern int owLevel(int,int); +extern int owProgramPulse(int); + +// owlli for the internal (TINI) ow bus +extern uchar iowTouchReset(void); +extern uchar iowReadByte(void); +extern uchar iowWriteByte(uchar); +extern uchar iowBlock(uchar, uchar*, uchar); +extern uchar iowFirst(uchar do_reset, uchar alarm_only); +extern uchar iowNext(uchar do_reset, uchar alarm_only); +extern uchar iowSpeed(int speed); +extern uchar iowLevel(int level); +extern uchar iowProgramPulse(void); +extern void iowSerialNum(uchar *, uchar); + +// owsesu.c +extern int owAcquire(int,char *, char *); +//extern int owAcquire(int,char *); +extern void owRelease(int, char *); +//extern void owRelease(int); + +// findtype.c +extern int FindDevices(int, uchar FamilySN[][8], int, int); + +// offile.c +int owReadFile(int,uchar *,uchar *); +int owFormatWriteFile(int,uchar *, int, uchar *); + +// sdcc has no exit +#define exit return +// sdcc has no double +#define double float +// sdcc has no key_abort +#define key_abort Serial0CharArrived diff --git a/device/examples/ds390/ow390/ownetu.c b/device/examples/ds390/ow390/ownetu.c new file mode 100755 index 00000000..ea343268 --- /dev/null +++ b/device/examples/ds390/ow390/ownetu.c @@ -0,0 +1,549 @@ +//--------------------------------------------------------------------------- +// 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.00 +// +// 1.02 -> 1.03 Removed caps in #includes for Linux capatibility +// 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for +// multiple ports. +// + +#include "ownet.h" +#include "ds2480.h" + +// local functions +static int bitacc(int,int,int,uchar *); + +// globally used +uchar SerialNum[MAX_PORTNUM][8]; + +// local variables for this module to hold search state information +static int LastDiscrepancy[MAX_PORTNUM]; +static int LastFamilyDiscrepancy[MAX_PORTNUM]; +static int LastDevice[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. +// +int owFirst(int portnum, int do_reset, int 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. +// +int owNext(int portnum, int do_reset, int alarm_only) +{ + int i,tmp_last_desc,pos; + uchar tmp_serial_num[8]; + uchar readbuffer[20],sendpacket[40]; + int 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; + 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; + 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; + } + } + } + + // 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, int do_read) +{ + int 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, int search_family) +{ + int i; + + // set the search state to find search_family type devices + SerialNum[portnum][0] = (uchar)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. +// +int owAccess(int portnum) +{ + uchar sendpacket[9]; + int 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) + return FALSE; + else + return TRUE; + } + } + + // 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. +// +int owVerify(int portnum, int alarm_only) +{ + int 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; + } + + // 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. +// +int owOverdriveAccess(int portnum) +{ + uchar sendpacket[8]; + int 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; + } + } + } + + // 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 +// +int bitacc(int op, int state, int loc, uchar *buf) +{ + int nbyt,nbit; + + nbyt = (loc / 8); + nbit = loc - (nbyt * 8); + + if (op == WRITE_FUNCTION) + { + if (state) + buf[nbyt] |= (0x01 << nbit); + else + buf[nbyt] &= ~(0x01 << nbit); + + return 1; + } + else + return ((buf[nbyt] >> nbit) & 0x01); +} diff --git a/device/examples/ds390/ow390/owsesu.c b/device/examples/ds390/ow390/owsesu.c new file mode 100755 index 00000000..b26eec43 --- /dev/null +++ b/device/examples/ds390/ow390/owsesu.c @@ -0,0 +1,97 @@ +//--------------------------------------------------------------------------- +// 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.00 +// +// History: 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for +// multiple ports. + +#include +#include "ownet.h" +#include "ds2480.h" + +// keep port name for later message when closing +static char portname[MAX_PORTNUM][128]; + +//--------------------------------------------------------------------------- +// 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. +// 'return_msg' - zero terminated return message. +// +// Returns: TRUE - success, COM port opened +// +int owAcquire(int portnum, char *port_zstr, char *return_msg) +{ + int cnt=0; + portname[portnum][0] = 0; + + // attempt to open the communications port + if (OpenCOM(portnum,port_zstr)) + cnt += sprintf(&return_msg[cnt],"%s opened\n",port_zstr); + else + { + cnt += sprintf(&return_msg[cnt],"Could not open port %s," + " aborting.\nClosing port %s.\n",port_zstr,port_zstr); + return FALSE; + } + printf (return_msg); // TODO: tini hack + + // detect DS2480 + if (DS2480Detect(portnum)) + cnt += sprintf(&return_msg[cnt],"DS2480-based adapter detected\n"); + else + { + cnt += sprintf(&return_msg[cnt],"DS2480-based adapter not detected, aborting program\n"); + cnt += sprintf(&return_msg[cnt],"Closing port %s.\n",port_zstr); + CloseCOM(portnum); + return FALSE; + } + + // success + sprintf(portname[portnum],"%s",port_zstr); + 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. +// 'return_msg' - zero terminated return message. +// +void owRelease(int portnum, char *return_msg) +{ + // close the communications port + sprintf(return_msg,"Closing port %s.\n",portname[portnum]); + CloseCOM(portnum); +} diff --git a/device/examples/ds390/ow390/owtrnu.c b/device/examples/ds390/ow390/owtrnu.c new file mode 100755 index 00000000..bf67642b --- /dev/null +++ b/device/examples/ds390/ow390/owtrnu.c @@ -0,0 +1,530 @@ +//--------------------------------------------------------------------------- +// 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 DS2480 (U) serial interface chip. +// +// Version: 2.00 +// +// 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. +// + +#include "ownet.h" +#include "ds2480.h" + +// local functions +static int Write_Scratchpad(int,uchar *,int,int); +static int Copy_Scratchpad(int,int,int); + +//-------------------------------------------------------------------------- +// 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 +// +int owBlock(int portnum, int do_reset, uchar *tran_buf, int tran_len) +{ + uchar sendpacket[150]; + int sendlen=0,pos,i; + + // check for a block too big + if (tran_len > 64) + return FALSE; + + // check if need to do a owTouchReset first + if (do_reset) + { + if (!owTouchReset(portnum)) + 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; + } + + // 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 +// +// +int owReadPacketStd(int portnum, int do_access, int start_page, uchar *read_buf) +{ + int 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 + } + } + + // 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 +// +// +int owWritePacketStd(int portnum, int start_page, uchar *write_buf, + int write_len, int is_eprom, int crc_type) +{ + uchar construct_buffer[32]; + int i,buffer_cnt=0,start_address,do_access; + ushort lastcrc16; + + // 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)) + return FALSE; + + // copy the scratchpad + if (!Copy_Scratchpad(portnum,start_page,buffer_cnt)) + 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]) + 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 +// +int owProgramByte(int portnum, int write_byte, int addr, int write_cmd, + int crc_type, int do_access) +{ + ushort lastcrc16; + uchar lastcrc8; + + // optionally access the device + if (do_access) + { + if (!owAccess(portnum)) + return -1; + + // send the write command + if (!owWriteByte(portnum,write_cmd)) + return -1; + + // send the address + if (!owWriteByte(portnum,addr & 0xFF)) + return -1; + if (!owWriteByte(portnum,addr >> 8)) + return -1; + } + + // send the data to write + if (!owWriteByte(portnum,write_byte)) + 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) + 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)) + 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 +// +// +int Write_Scratchpad(int portnum, uchar *write_buf, int start_page, int write_len) +{ + int 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] != (int)((start_page << 5) & 0xFF)) || + (sendpacket[11] != (int)(start_page >> 3)) || + (sendpacket[12] != (int)(write_len - 1))) + return FALSE; + + // verify each data byte + for (i = 0; i < write_len; i++) + if (sendpacket[i+13] != write_buf[i]) + return FALSE; + + // must have verified + return TRUE; + } + } + + // failed a block tranfer + return FALSE; +} + +//-------------------------------------------------------------------------- +// Copy the contents of the scratchpad to its intended nv ram page. The +// page and length of the data is needed to build the authorization bytes +// to copy. +// +// '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 +// +int Copy_Scratchpad(int portnum, int start_page, int write_len) +{ + int 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] != (int)((start_page << 5) & 0xFF)) || + (sendpacket[11] != (int)(start_page >> 3)) || + (sendpacket[12] != (int)(write_len - 1)) || + (sendpacket[13] & 0xF0)) + return FALSE; + else + return TRUE; + } + + // failed a block tranfer + return FALSE; +} + diff --git a/device/examples/ds390/ow390/swt12.c b/device/examples/ds390/ow390/swt12.c new file mode 100644 index 00000000..50604583 --- /dev/null +++ b/device/examples/ds390/ow390/swt12.c @@ -0,0 +1,258 @@ +//--------------------------------------------------------------------------- +// 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. +//-------------------------------------------------------------------------- +// +// swt12.c - Modifies Channel A and B and returns info byte data for +// the DS2406 and DS2407. +// version 2.00 + + +// Include files +#include +#include "ownet.h" +#include "swt12.h" + +//---------------------------------------------------------------------- +// SUBROUTINE - ReadSwitch12 +// +// This routine gets the Channel Info Byte and returns it. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'ClearActivity' - To reset the button +// +// Returns: (-1) If the Channel Info Byte could not be read. +// (Info Byte) If the Channel Info Byte could be read. +// +int ReadSwitch12(int portnum, int ClearActivity) +{ + int rt=-1; //this is the return value depending if the byte was read + int trans_cnt=0; //this is the counter for the number of bytes to send + uchar transfer[30]; //this is the whole block of byte info + + // access and verify it is there + if (owAccess(portnum)) + { + // reset CRC + setcrc16(portnum,0); + + // channel access command + transfer[trans_cnt++] = 0xF5; + docrc16(portnum,0xF5); + + // control bytes + if (ClearActivity) + { + transfer[trans_cnt++] = 0xD5; + docrc16(portnum,0xD5); + } + else + { + transfer[trans_cnt++] = 0x55; + docrc16(portnum,0x55); + } + + transfer[trans_cnt++] = 0xFF; + docrc16(portnum,0xFF); + + // read the info byte + transfer[trans_cnt++] = 0xFF; + + // dummy data + transfer[trans_cnt++] = 0xFF; + transfer[trans_cnt++] = 0xFF; + transfer[trans_cnt++] = 0xFF; + + if (owBlock(portnum,FALSE,transfer,trans_cnt)) + { + rt = transfer[3]; + // read a dummy read byte and CRC16 + docrc16(portnum,transfer[trans_cnt-4]); + docrc16(portnum,transfer[trans_cnt-3]); + docrc16(portnum,transfer[trans_cnt-2]); + if(docrc16(portnum,transfer[trans_cnt-1]) != 0xB001) + rt = -1; + } + } + else + rt = -1; + + return rt; +} + +//---------------------------------------------------------------------- +// SUBROUTINE - SetSwitch12 +// +// This routine sets the channel state of the specified DS2406 +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'SerialNum' - Serial Number of DS2406 to set the switch state +// 'State' - Is a type containing what to set A and/or B to. It +// also contains the other fields that maybe written later +// +// Returns: TRUE(1) State of DS2406 set and verified +// FALSE(0) could not set the DS2406, perhaps device is not +// in contact +// +int SetSwitch12(int portnum, uchar *SerialNum, SwitchProps *State) +{ + ushort st; + int rt=FALSE; + uchar send_block[30]; + int send_cnt=0; + + setcrc16(portnum,0); + + // set the device serial number to the counter device + owSerialNum(portnum,SerialNum,FALSE); + + // access the device + if (owAccess(portnum)) + { + // create a block to send that reads the counter + // write status command + send_block[send_cnt++] = 0x55; + docrc16(portnum,0x55); + + // address of switch state + send_block[send_cnt++] = 0x07; + docrc16(portnum,0x07); + send_block[send_cnt++] = 0x00; + docrc16(portnum,0x00); + + // write state + st = 0x1F; + if(!State->Chan_B) st |= 0x40; + if(!State->Chan_A) st |= 0x20; + // more ifs can be added here for the other fields. + + send_block[send_cnt++] = (uchar)st; + docrc16(portnum,st); + + // read CRC16 + send_block[send_cnt++] = 0xFF; + send_block[send_cnt++] = 0xFF; + + // now send the block + if (owBlock(portnum,FALSE,send_block,send_cnt)) + { + // perform the CRC16 on the last 2 bytes of packet + docrc16(portnum,send_block[send_cnt-2]); + + // verify crc16 is correct + if(docrc16(portnum,send_block[send_cnt-1]) == 0xB001) + rt = TRUE; + } + } + + // return the result flag rt + return rt; +} + + +//---------------------------------------------------------------------- +// SUBROUTINE - SwitchStateToString12 +// +// 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. +// +int SwitchStateToString12(int infobyte, char *outstr) +{ + + int cnt = 0; + + if(infobyte & 0x40) + { + cnt += sprintf(outstr+cnt, "%s", "Channel A and B\n"); + + if(infobyte & 0x80) + cnt += sprintf(outstr+cnt, "%s", "Supply\n"); + else + cnt += sprintf(outstr+cnt, "%s", "No Supply\n"); + + if(infobyte & 0x20) + cnt += sprintf(outstr+cnt, "%s", "Activity on PIO-B\n"); + else + cnt += sprintf(outstr+cnt, "%s", "No activity on PIO-B\n"); + + if(infobyte & 0x10) + cnt += sprintf(outstr+cnt, "%s", "Activity on PIO-A\n"); + else + cnt += sprintf(outstr+cnt, "%s", "No activity on PIO-A\n"); + + if(infobyte & 0x08) + cnt += sprintf(outstr+cnt, "%s", "Hi level on PIO B\n"); + else + cnt += sprintf(outstr+cnt, "%s", "Lo level on PIO B\n"); + + if(infobyte & 0x04) + cnt += sprintf(outstr+cnt, "%s", "Hi level on PIO A\n"); + else + cnt += sprintf(outstr+cnt, "%s", "Lo level on PIO A\n"); + + if(infobyte & 0x02) + cnt += sprintf(outstr+cnt, "%s", "Channel B off\n"); + else + cnt += sprintf(outstr+cnt, "%s", "Channel B on\n"); + + if(infobyte & 0x01) + cnt += sprintf(outstr+cnt, "%s", "Channel A off\n"); + else + cnt += sprintf(outstr+cnt, "%s", "Channel A on\n"); + } + else + { + cnt += sprintf(outstr+cnt, "%s", "Channel A\n"); + + if(infobyte & 0x80) + cnt += sprintf(outstr+cnt, "%s", "Supply\n"); + else + cnt += sprintf(outstr+cnt, "%s", "No Supply\n"); + + if(infobyte & 0x10) + cnt += sprintf(outstr+cnt, "%s", "Activity on PIO-A\n"); + else + cnt += sprintf(outstr+cnt, "%s", "No activity on PIO-A\n"); + + if(infobyte & 0x04) + cnt += sprintf(outstr+cnt, "%s", "Hi level on PIO A\n"); + else + cnt += sprintf(outstr+cnt, "%s", "Lo level on PIO A\n"); + + if(infobyte & 0x01) + cnt += sprintf(outstr+cnt, "%s", "Channel A off\n"); + else + cnt += sprintf(outstr+cnt, "%s", "Channel A on\n"); + + } + + return cnt; +} + + diff --git a/device/examples/ds390/ow390/swt12.h b/device/examples/ds390/ow390/swt12.h new file mode 100644 index 00000000..f13ba119 --- /dev/null +++ b/device/examples/ds390/ow390/swt12.h @@ -0,0 +1,13 @@ +typedef struct tagSRAM +{ + uchar Supply; + uchar Chan_B; + uchar Chan_A; + uchar Chan_Sel; + uchar Sour_Sel; + uchar Polarity; +} SwitchProps; + +int ReadSwitch12(int,int); +int SetSwitch12(int,uchar *,SwitchProps*); +int SwitchStateToString12(int,char *); diff --git a/device/examples/ds390/ow390/swtloop.c b/device/examples/ds390/ow390/swtloop.c new file mode 100755 index 00000000..09c60062 --- /dev/null +++ b/device/examples/ds390/ow390/swtloop.c @@ -0,0 +1,218 @@ +//--------------------------------------------------------------------------- +// 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. +//-------------------------------------------------------------------------- +// +// swtloop.C - Goes through the testing of the DS2406(DS2407) switch +// Version 2.00 + + +// Include files +#include +#include +#include "ownet.h" +#include "swt12.h" + +// Constant definition +#define MAXDEVICES 15 + +// tini hack +int argc=2; +char *argv[]={__FILE__, "exow"}; +#define getkeystroke getchar + +//-------------------------------------------------------------------------- +// This is the begining of the program that tests the different Channels +int main() //short argc, char **argv) +{ + char return_msg[128]; //returned message from 1-wire operations + int i,j,k,n; //loop counters + short test=0; //info byte data + short clear=0; //used to clear the button + SwitchProps sw; //used to set Channel A and B + uchar SwitchSN[MAXDEVICES][8]; //the serial numbers for the devices + int num; //for the number of devices present + int ch; //inputed character from user + char out[140]; //used for output of the info byte data + int portnum=0; + + //---------------------------------------- + // Introduction header + printf("\n/---------------------------------------------\n"); + printf(" swtest - V2.00\n" + " The following is a test to excersize the\n" + " different channels on the DS2406.\n"); + printf(" Press any CTRL-C to stop this program.\n\n"); + + // check for required port name + if (argc != 2) + { + printf("1-Wire Net name required on command line!\n" + " (example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" " + "(Linux DS2480),\"1\" (Win32 TMEX)\n"); + exit(1); + } + + // attempt to acquire the 1-Wire Net + if (!owAcquire(portnum, argv[1], return_msg)) + { + printf("%s",return_msg); + exit(1); + } + + // success + printf("%s",return_msg); + + // this is to get the number of the devices and the serial numbers + num = FindDevices(portnum, &SwitchSN[0], SWITCH_FAMILY, MAXDEVICES); + + // setting up the first print out for the frist device + owSerialNum(portnum, SwitchSN[0], FALSE); + + j=1; + n=0; + do + { + // This is for after the different combinations of channels + // have been tested to reset to a different device to be tested. + if( ((test & 0x40) && (j==5)) || + ((!(test & 0x40)) && (j==3)) ) + { + printf("\n\n"); + for(k=0; k < num; k++) + { + printf("%d ", k+1); + for(i=7; i>=0; i--) + { + printf("%02X", SwitchSN[k][i]); + } + printf("\n"); + } + printf("%d To quit or any other key.\n", k+1); + + printf("\n"); + printf("Pick a device\n"); + + ch = getkeystroke(); + n = 0; + n = (10*n + (ch - '0')) - 1; + + if( (n>num-1) || (n<0) ) + { + n = 0; //used to finish off the loop + break; + } + + owSerialNum(portnum, SwitchSN[n], FALSE); + j = 1; + } + printf("\n"); + + test = ReadSwitch12(portnum,clear); + + // This looks at the info byte to determine if it is a + // two or one channel device. + if(test & 0x40) + { + + switch(j) + { + case 1: + sw.Chan_A = 0; + sw.Chan_B = 0; + break; + case 2: + sw.Chan_A = 0; + sw.Chan_B = 1; + break; + case 3: + sw.Chan_A = 1; + sw.Chan_B = 0; + break; + case 4: + sw.Chan_A = 1; + sw.Chan_B = 1; + break; + default: + sw.Chan_A = 1; + sw.Chan_B = 1; + j=0; + break; + } + } + else + { + switch(j) + { + case 1: + sw.Chan_B = 0; + sw.Chan_A = 0; + break; + case 2: + sw.Chan_B = 0; + sw.Chan_A = 1; + break; + default: + sw.Chan_B = 0; + sw.Chan_A = 1; + j = 0; + break; + } + } + + if(!SetSwitch12(portnum, SwitchSN[n], &sw)) + { + msDelay(50); + if(SetSwitch12(portnum, SwitchSN[n], &sw)) + msDelay(50); + else + printf("Switch not set\n"); + } + + test = ReadSwitch12(portnum,clear); + + printf("\n"); + + for(i=7; i>=0; i--) + { + printf("%02X", SwitchSN[n][i]); + } + printf("\n"); + + SwitchStateToString12(test, out); + printf("%s", out); + + j++; + + } + while(1); + + // release the 1-Wire Net + owRelease(portnum,return_msg); + printf("%s",return_msg); + exit(0); + + return 0; +} + diff --git a/device/examples/ds390/ow390/swtoper.c b/device/examples/ds390/ow390/swtoper.c new file mode 100755 index 00000000..2954eb86 --- /dev/null +++ b/device/examples/ds390/ow390/swtoper.c @@ -0,0 +1,219 @@ +//--------------------------------------------------------------------------- +// 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. +//-------------------------------------------------------------------------- +// +// swtoper.C - Menu-driven test of DS2406(DS2407) 1-Wire switch +// version 2.00 + + +// Include files +#include +#include +#include +#include "ownet.h" +#include "swt12.h" + +// Constant definition +#define MAXDEVICES 15 + +// tini hack +int argc=2; +char *argv[]={__FILE__, "exow"}; +#define getkeystroke getchar + +//--------------------------------------------------------------------------- +// The main program that performs the operations on switches +// +int main() //short argc, char **argv) +{ + char return_msg[128]; //returned message from 1-wire operations + short test; //info byte data + short clear=0; //used to clear the button + short done; //to tell when the user is done + SwitchProps sw; //used to set Channel A and B + uchar SwitchSN[MAXDEVICES][8]; //the serial number for the devices + int num; //for the number of devices present + int ch; //inputed character from user + int i,j,n; //loop counters and indexes + char out[140]; //used for output of the info byte data + int count; //the number of characters in the info byte data + int portnum=0; + + //---------------------------------------- + // Introduction header + printf("\n/---------------------------------------------\n"); + printf(" Switch - V2.00\n" + " The following is a test to excersize the \n" + " setting of the state in a DS2406.\n"); + + printf(" Press any CTRL-C to stop this program.\n\n"); + + // check for required port name + if (argc != 2) + { + printf("1-Wire Net name required on command line!\n" + " (example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" " + "(Linux DS2480),\"1\" (Win32 TMEX)\n"); + exit(1); + } + + // attempt to acquire the 1-Wire Net + if (!owAcquire(portnum, argv[1], return_msg)) + { + printf("%s",return_msg); + exit(1); + } + + // success + printf("%s",return_msg); + + // this is to get the number of the devices and the serial numbers + num = FindDevices(portnum, &SwitchSN[0], SWITCH_FAMILY, MAXDEVICES); + + // setting up the first print out for the frist device + owSerialNum(portnum, SwitchSN[0], FALSE); + + printf("\n"); + n=0; + if(owAccess(portnum)) + { + // loop while not done + do + { + test = ReadSwitch12(portnum, clear); + + for(i=7; i>=0; i--) + printf("%02X", SwitchSN[n][i]); + + printf("\n"); + + count = SwitchStateToString12(test, out); + printf("%s", out); + + // print menu + printf("\n\n(1) Display the switch Info\n" + "(2) Clear activity Latches\n" + "(3) Set Flip Flop(s) on switch\n" + "(4) Select different device\n" + "(5) Quit\n" + "Select a Number:"); + ch = getkeystroke(); + printf("\n\n"); + + // do something from the menu selection + clear = FALSE; + switch(ch) + { + case '1': // Display the switch Info + done = FALSE; + break; + case '2': // Clear activity Latches + clear = TRUE; + done = FALSE; + break; + case '3': // Set Flip Flop(s) on switch + printf("Channel %c Flip Flop (1 set, 0 clear):",'A'); + ch = getkeystroke(); + if (ch == '0') + sw.Chan_A = 0; + else + sw.Chan_A = 1; + printf("\n"); + + if(test & 0x40) + { + printf("Channel %c Flip Flop (1 set, 0 clear):",'B'); + ch = getkeystroke(); + if (ch == '0') + sw.Chan_B = 0; + else + sw.Chan_B = 1; + printf("\n"); + } + else + { + printf("\n"); + sw.Chan_B = 0; + } + printf("\n"); + + if(!SetSwitch12(portnum, SwitchSN[n], &sw)) + { + msDelay(50); + if(SetSwitch12(portnum, SwitchSN[n], &sw)) + msDelay(50); + else + printf("Switch not set\n"); + } + done = FALSE; + break; + case '4': // Switch Devices + for(j=0; j < num; j++) + { + printf("%d ", j+1); + for(i=7; i>=0; i--) + { + printf("%02X", SwitchSN[j][i]); + } + printf("\n"); + } + printf("\n"); + + do + { + printf("Pick a device\n"); + ch = getkeystroke(); + n = 0; + n = (10*n + (ch - '0')) - 1; + printf("\n"); + } + while((!isalnum(ch)) || (n>num-1)); + printf("\n"); + + n = 0; + n = (10*n + (ch - '0')) - 1; + + owSerialNum(portnum, SwitchSN[n], FALSE); + + done = FALSE; + break; + + case '5': case 'q': case 'Q': // Done + done = TRUE; + break; + default: + break; + } + } + while (!done); + } + //One Wire Access + owRelease(portnum,return_msg); + printf("%s",return_msg); + exit(0); + + return 0; +} + diff --git a/device/examples/ds390/ow390/temp.c b/device/examples/ds390/ow390/temp.c new file mode 100755 index 00000000..a9c62a28 --- /dev/null +++ b/device/examples/ds390/ow390/temp.c @@ -0,0 +1,154 @@ +//--------------------------------------------------------------------------- +// 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. +//--------------------------------------------------------------------------- +// +// temp.c - Application to find and read the 1-Wire Net +// DS1920/DS1820/DS18S20 - temperature measurement. +// +// This application uses the files from the 'Public Domain' +// 1-Wire Net libraries ('general' and 'userial'). +// +// +// Version: 2.00 +// + +#include +#include +#include "ownet.h" +#include "temp10.h" + +// defines +#define MAXDEVICES 20 + +// local functions +static void PrintSerialNum(uchar FamilySN[8]); + +// local serial numbers +static uchar FamilySN[MAXDEVICES][8]; + +// variables +static int family_code; + +// tini hack +int argc=2; +char *argv[]={__FILE__, "exow"}; + +//---------------------------------------------------------------------- +// Main Test for DS1920/DS1820 temperature measurement +// +int main() //short argc, char **argv) +{ + float current_temp; + char return_msg[128]; + int i = 0; + int j = 0; + int NumDevices=0; + int portnum = 0; + + //---------------------------------------- + // Introduction header + printf("\n/---------------------------------------------\n"); + printf(" Temperature application DS1920/DS1820 - Version 1.00 \n" + " The following is a test to excersize a DS1920/DS1820.\n" + " Temperature Find and Read from a: \n" + " DS1920/DS1820 (at least 1)\n\n"); + + printf(" Press any CTRL-C to stop this program.\n\n"); + printf(" Output [Serial Number(s) ........ Temp1(C)] \n\n"); + + // check for required port name + if (argc != 2) + { + printf("1-Wire Net name required on command line!\n" + " (example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" " + "(Linux DS2480),\"1\" (Win32 TMEX)\n"); + exit(1); + } + + + // attempt to acquire the 1-Wire Net + if (!owAcquire(portnum, argv[1], return_msg)) + { + printf("%s",return_msg); + exit(1); + } + + // success + printf("%s",return_msg); + + // Find the device(s) + NumDevices = FindDevices(portnum, &FamilySN[0], 0x10, MAXDEVICES); + if (NumDevices>0) + { + printf("\n"); + printf("Device(s) Found: \n"); + for (i = 0; i < NumDevices; i++) + { + PrintSerialNum(FamilySN[i]); + printf("\n"); + } + printf("\n\n"); + + // (stops on CTRL-C) + do + { + // read the temperature and print serial number and temperature + for (i = 0; i < NumDevices; i++) + { + + if (ReadTemperature(portnum, FamilySN[i],¤t_temp)) + { + PrintSerialNum(FamilySN[i]); + printf(" %5.1f \n", current_temp); + } + else + printf(" Error reading temperature, verify device present:%d\n", + owVerify(portnum, FALSE)); + } + printf("\n"); + } + while (!key_abort()); + } + else + printf("\n\n\nERROR, device DS1920/DS1820 not found!\n"); + + // release the 1-Wire Net + owRelease(portnum, return_msg); + printf("%s",return_msg); + exit(0); + + return 0; +} + +// ------------------------------------------------------------------------------- +// Read and print the serial number. +// +void PrintSerialNum(uchar FamilySN[8]) +{ + int i; + + for (i = 7; i>=0; i--) + printf("%02X", FamilySN[i]); +} diff --git a/device/examples/ds390/ow390/temp10.c b/device/examples/ds390/ow390/temp10.c new file mode 100644 index 00000000..31c46d32 --- /dev/null +++ b/device/examples/ds390/ow390/temp10.c @@ -0,0 +1,129 @@ +//--------------------------------------------------------------------------- +// 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. +// --------------------------------------------------------------------------- +// +// temp10.C - Module to read the DS1920/DS1820 - temperature measurement. +// +// Version: 2.00 +// +// --------------------------------------------------------------------------- +// +// +#include "ownet.h" +#include "temp10.h" + +//---------------------------------------------------------------------- +// Read the temperature of a DS1920/DS1820 +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'SerialNum' - Serial Number of DS1920/DS1820 to read temperature from +// 'Temp ' - pointer to variable where that temperature will be +// returned +// +// Returns: TRUE(1) temperature has been read and verified +// FALSE(0) could not read the temperature, perhaps device is not +// in contact +// +int ReadTemperature(int portnum, uchar *SerialNum, float *Temp) +{ + int rt=FALSE; + uchar send_block[30],lastcrc8; + int send_cnt=0, tsht, i, loop=0; + float tmp,cr,cpc; + + + setcrc8(portnum,0); + + // set the device serial number to the counter device + owSerialNum(portnum,SerialNum,FALSE); + + for (loop = 0; rt==FALSE && loop < 2; loop ++) + { + // access the device + if (owAccess(portnum)) + { + // send the convert temperature command + owTouchByte(portnum,0x44); + + // set the 1-Wire Net to strong pull-up + if (owLevel(portnum,MODE_STRONG5) != MODE_STRONG5) + return FALSE; + + // sleep for 1 second + msDelay(1000); + + // turn off the 1-Wire Net strong pull-up + if (owLevel(portnum,MODE_NORMAL) != MODE_NORMAL) + return FALSE; + + // access the device + if (owAccess(portnum)) + { + // create a block to send that reads the temperature + // read scratchpad command + send_block[send_cnt++] = 0xBE; + // now add the read bytes for data bytes and crc8 + for (i = 0; i < 9; i++) + send_block[send_cnt++] = 0xFF; + + // now send the block + if (owBlock(portnum,FALSE,send_block,send_cnt)) + { + // perform the CRC8 on the last 8 bytes of packet + for (i = send_cnt - 9; i < send_cnt; i++) + lastcrc8 = docrc8(portnum,send_block[i]); + + // verify CRC8 is correct + if (lastcrc8 == 0x00) + { + // calculate the high-res temperature + tsht = send_block[1]/2; + if (send_block[2] & 0x01) + tsht |= -128; + tmp = (float)(tsht); + cr = send_block[7]; + cpc = send_block[8]; + if (((cpc - cr) == 1) && (loop == 0)) + continue; + if (cpc == 0) + return FALSE; + else + tmp = tmp - (float)0.25 + (cpc - cr)/cpc; + + *Temp = tmp; + // success + rt = TRUE; + } + } + } + } + + } + + // return the result flag rt + return rt; + +} diff --git a/device/examples/ds390/ow390/temp10.h b/device/examples/ds390/ow390/temp10.h new file mode 100644 index 00000000..e4521088 --- /dev/null +++ b/device/examples/ds390/ow390/temp10.h @@ -0,0 +1 @@ +extern int ReadTemperature(int, uchar *, float *); diff --git a/device/examples/ds390/ow390/thermo21.c b/device/examples/ds390/ow390/thermo21.c new file mode 100644 index 00000000..82d3301b --- /dev/null +++ b/device/examples/ds390/ow390/thermo21.c @@ -0,0 +1,1336 @@ +//--------------------------------------------------------------------------- +// 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 +#include "time.h" +#include +#include "ownet.h" +#include "thermo21.h" + +// a hack for sdcc/TINI, just printf to stdout +int fprintf (FILE *fp, xdata char *format, ...) reentrant { + va_list arg; + *fp; // hush the compiler + va_start(arg, format); + vsprintf(NULL, format, arg); + va_end(arg); +} + +static int RunThermoScript(int,ThermoStateType *,ThermoScript script[], FILE *fp); +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); + +// 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"}}; + +// 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 (!Serial0CharArrived()); + + // 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]; + + ErrorCount; // hush the compiler + + // 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"); + *Status = STATUS_INPROGRESS; + } + 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); + + // 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; + } + + // 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 +#ifdef LetsCrashTheCompiler + for (i = 0; i < 32; i++) + finalbuf[i + (*last_pg - start_pg) * 32] = pkt[len - 34 + i]; +#endif + { + ushort k; + for (i = 0; i < 32; i++) { + k=i + (*last_pg - start_pg) * 32; + finalbuf[k] = 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; + time_t tlong; + struct tm *tstruct; + + // 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 = ((int)mstatus->status_raw[0x13] << 8) | + mstatus->status_raw[0x12]; + + // number of samples in this mission + mstatus->mission_samples = ((long)mstatus->status_raw[0x1C] << 16) | + ((int)mstatus->status_raw[0x1B] << 8) | + mstatus->status_raw[0x1A]; + + // total number of samples + mstatus->samples_total = ((long)mstatus->status_raw[0x1F] << 16) | + ((int)mstatus->status_raw[0x1E] << 8) | + mstatus->status_raw[0x1D]; + + // 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 + 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); + + // 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; + struct tm *tstruct; + + // clear the buffer + for (i = 0; i < 32; i++) + mstatus->status_raw[i] = 0; + + // Real Time Clock + time(&tlong); + tlong++; // add 1 second + tstruct = localtime(&tlong); + // convert to BCD + 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)); + // 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; + time_t tlong; + struct tm *tstruct; + + // title + cnt += sprintf(&str[cnt],"Mission State\n-------------\n"); + + // serial number + cnt += sprintf(&str[cnt],"Serial Number of DS1921: "); + 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 time: %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: %d\n",mstatus->mission_samples); + + // device total samples + cnt += sprintf(&str[cnt],"Device total samples: %d\n",mstatus->samples_total); + + // temperature display mode + cnt += sprintf(&str[cnt],"Temperature 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); + + // 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); + + // 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] | ((int)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 = ((long)alarm->alarm_raw[i + 2] << 16) | + ((int)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 = ((long)alarm->alarm_raw[i + 2] << 16) | + ((int)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); +} diff --git a/device/examples/ds390/ow390/thermo21.h b/device/examples/ds390/ow390/thermo21.h new file mode 100644 index 00000000..9a8d1f94 --- /dev/null +++ b/device/examples/ds390/ow390/thermo21.h @@ -0,0 +1,179 @@ +//--------------------------------------------------------------------------- +// 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 + +// hacks for sdcc->TINI +#define NULL ((void*)0) +#define FILE void +#define stdin ((void *)0) +#define stdout ((void *)0) +#define stderr ((void *)0) +int fprintf (FILE *fp, xdata char *format, ...) reentrant; + +// 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; + +// structure to hold each state in the StateMachine +typedef struct +{ + int Step; + char StepDescription[50]; + +} ThermoScript; + +// Global Function Prototypes + int DownloadThermo(int,uchar *,ThermoStateType *, FILE *); +int ReadThermoStatus(int,uchar *,ThermoStateType *, FILE *); +int MissionThermo(int,uchar *,ThermoStateType *, FILE *); +void SecondsToDate(timedate *, ulong); +ulong DateToSeconds(timedate *); +uchar BCDToBin(uchar); + void InterpretStatus(MissionStatus *); + void MissionStatusToString(MissionStatus *, int, char *); +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); + +#endif diff --git a/device/examples/ds390/ow390/thermodl.c b/device/examples/ds390/ow390/thermodl.c new file mode 100644 index 00000000..13a4b7e7 --- /dev/null +++ b/device/examples/ds390/ow390/thermodl.c @@ -0,0 +1,173 @@ +//--------------------------------------------------------------------------- +// 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. +//--------------------------------------------------------------------------- +// +// thermodl.c - This utility uses to download the results of the +// current mission of a DS1921 Thermochron iButton. +// +// Version: 2.00 +// +// History: +// 1.03 -> 2.00 Reorganization of Public Domain Kit +// Y2K update, display all histogram bins, debug +// dump. Supports multiple thermochons. +// + +#include +#include +#include "ownet.h" +#include "thermo21.h" + +// TINI hack +#define ExitProg(msg,exit_code) {printf("%s\n",msg); exit(exit_code);} + +// defines +#define MAXDEVICES 20 + +// local function prototypes +static void PrintResults(ThermoStateType *,FILE *,int); + +//---------------------------------------------------------------------- +// This is the Main routine for thermodl. +// +int main() +{ + int Fahrenheit=FALSE,num,i,j; + FILE *fp=stdout; + char return_msg[128]; + ThermoStateType ThermoState; + uchar ThermoSN[MAXDEVICES][8]; //the serial numbers for the devices + int portnum=0; + + // attempt to acquire the 1-Wire Net + if (!owAcquire(portnum,"")) + return 0; + + // success + + //---------------------------------------- + // Introduction + printf("\n/----------------------------------------------\n"); + printf(" Find and download DS1921 Thermochron iButton(s)\n" + " Version 2.00\n\n"); + + // check arguments for temperature conversion and filename + Fahrenheit = FALSE; + + // get list of Thermochron's + num = FindDevices(portnum, &ThermoSN[0],THERMO_FAM, MAXDEVICES); + + // check if not present or more then 1 present + if (num == 0) + ExitProg("Thermochron not present on 1-Wire\n",1); + + // loop to download each Thermochron + for (i = 0; i < num; i++) + { + // set the serial number portion in the thermo state + printf("\nDownloading: "); + for (j = 7; j >= 0; j--) + { + ThermoState.MissStat.serial_num[j] = ThermoSN[i][j]; + printf("%02X",ThermoSN[i][j]); + } + printf("\n"); + + // download the Thermochron found + if (DownloadThermo(portnum,&ThermoSN[i][0],&ThermoState,stdout)) + { + // interpret the results of the download + InterpretStatus(&ThermoState.MissStat); + InterpretAlarms(&ThermoState.AlarmData, &ThermoState.MissStat); + InterpretHistogram(&ThermoState.HistData); + InterpretLog(&ThermoState.LogData, &ThermoState.MissStat); + + // print the output + PrintResults(&ThermoState,fp,Fahrenheit); + } + else + { + fprintf(fp,"\nError downloading device: "); + for (j = 0; j < 8; j++) + fprintf(fp,"%02X",ThermoSN[i][j]); + fprintf(fp,"\n"); + } + } + + // release the 1-Wire Net + owRelease(portnum); + printf("\n%s",return_msg); + ExitProg("End program normally\n",0); + + return 0; +} + +//-------------------------------------------------------------------------- +// Prints the mission data optionaly to a file or standard out +// +void PrintResults(ThermoStateType *ThermoState, FILE *fp, int ConvertToF) +{ + //char *str; + char str[80000]; + + // check if need to use standard out + if (fp == NULL) + fp = stdout; + + // get big block to use as a buffer +#if 0 + str = malloc(80000); + if (str == NULL) + { + printf("Insufficient memory available to print!\n"); + return; + } +#endif + + // mission status + MissionStatusToString(&ThermoState->MissStat, ConvertToF, &str[0]); + fprintf(fp,"\n%s\n",str); + + // alarm events + AlarmsToString(&ThermoState->AlarmData, &str[0]); + fprintf(fp,"%s\n",str); + + // histogram + HistogramToString(&ThermoState->HistData, ConvertToF, &str[0]); + fprintf(fp,"%s\n",str); + + // log data + LogToString(&ThermoState->LogData, ConvertToF, &str[0]); + fprintf(fp,"%s\n",str); + + // debug raw data + DebugToString(&ThermoState->MissStat, &ThermoState->AlarmData, + &ThermoState->HistData, &ThermoState->LogData, &str[0]); + fprintf(fp,"%s\n",str); + + // free the memory block used + //free(str); +} + diff --git a/device/examples/ds390/ow390/time.c b/device/examples/ds390/ow390/time.c new file mode 100755 index 00000000..3b613539 --- /dev/null +++ b/device/examples/ds390/ow390/time.c @@ -0,0 +1,24 @@ +#include "time.h" + +// let's just pretend it's 01 jan 1970 00.00:00 for now + +time_t time(time_t *t) { + *t=0; + return *t; +} + +struct tm lastTime; + +struct tm *localtime(const time_t *timep) { + timep; // hush the compiler + lastTime.tm_sec=0; + lastTime.tm_min=0; + lastTime.tm_hour=0; + lastTime.tm_mday=1; + lastTime.tm_mon=0; + lastTime.tm_year=101; + lastTime.tm_wday=0; + lastTime.tm_yday=0; + lastTime.tm_isdst=0; + return &lastTime; +} diff --git a/device/examples/ds390/ow390/time.h b/device/examples/ds390/ow390/time.h new file mode 100644 index 00000000..54dd1504 --- /dev/null +++ b/device/examples/ds390/ow390/time.h @@ -0,0 +1,17 @@ +struct tm +{ + int tm_sec; /* Seconds. [0-60] (1 leap second) */ + int tm_min; /* Minutes. [0-59] */ + int tm_hour; /* Hours. [0-23] */ + int tm_mday; /* Day. [1-31] */ + int tm_mon; /* Month. [0-11] */ + int tm_year; /* Year - 1900. */ + int tm_wday; /* Day of week. [0-6] */ + int tm_yday; /* Days in year.[0-365] */ + int tm_isdst; /* Daylight saving time */ +}; + +typedef unsigned long time_t; + +time_t time(time_t *t); +struct tm *localtime(time_t *timep); diff --git a/device/examples/ds390/ow390/tinilnk.c b/device/examples/ds390/ow390/tinilnk.c new file mode 100644 index 00000000..95e95e90 --- /dev/null +++ b/device/examples/ds390/ow390/tinilnk.c @@ -0,0 +1,278 @@ +//--------------------------------------------------------------------------- +// 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. +//--------------------------------------------------------------------------- +// +// TODO.C - COM functions required by MLANLL.C, MLANTRNU, MLANNETU.C and +// MLanFile.C for MLANU to communicate with the DS2480 based +// Universal Serial Adapter 'U'. Fill in the platform specific code. +// +// Version: 1.02 +// +// History: 1.00 -> 1.01 Added function msDelay. +// +// 1.01 -> 1.02 Changed to generic OpenCOM/CloseCOM for easier +// use with other platforms. +// + +//-------------------------------------------------------------------------- +// Copyright (C) 1998 Andrea Chambers and University of Newcastle upon Tyne, +// All Rights Reserved. +//-------------------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE UNIVERSITY OF NEWCASTLE UPON TYNE OR ANDREA CHAMBERS +// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//--------------------------------------------------------------------------- +// +// LinuxLNK.C - COM functions required by MLANLLU.C, MLANTRNU.C, MLANNETU.C +// and MLanFile.C for MLANU to communicate with the DS2480 based +// Universal Serial Adapter 'U'. Platform specific code. +// +// Version: 1.03 +// History: 1.00 -> 1.03 modifications by David Smiczek +// Changed to use generic OpenCOM/CloseCOM +// Pass port name to OpenCOM instead of hard coded +// Changed msDelay to handle long delays +// Reformatted to look like 'TODO.C' +// Added #include "ds2480.h" to use constants. +// Added function SetBaudCOM() +// Added function msGettick() +// Removed delay from WriteCOM(), used tcdrain() +// Added wait for byte available with timeout using +// select() in ReadCOM() +// +// 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. +// + +#include + +#include "ownet.h" +#include "ds2480.h" + +//--------------------------------------------------------------------------- +// 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 +// ignored for now +// +// +// Returns: TRUE(1) - success, COM port opened +// FALSE(0) - failure, could not open specified port +// +int OpenCOM(int portnum, char *port_zstr) +{ + unsigned long baud=9600; + + //printf ("OpenCOM(%d,\"%s\")\n", portnum, port_zstr); + + // hush the compiler + portnum; + port_zstr; + + Serial1Init(baud,1); + + 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) +{ + //printf ("CloseCOM(%d)\n", portnum); + + // hush the compiler + 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 +// +int WriteCOM(int portnum, int outlen, uchar *outbuf) +{ + int i; + + //printf ("WriteCOM(%d, %d,...): ", portnum, outlen, outbuf); + + // hush the compiler + portnum; + + for (i=0; i 1.03 Removed caps in #includes for Linux capatibility +// Removed "ds2480.h", and +// includes because not needed +// Added "ownet.h" include to define TRUE/FALSE +// Prompt to search again +// Changed to use Acquire/Release 1-Wire Net functions +// 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for +// multiple ports. Don't stop loop at end of each +// search round. + +#include +#include +#include "ownet.h" + +// local funcitons +static void PrintSerialNum(int); + +// tini hack +int argc=2; +char *argv[]={__FILE__, "exow"}; + +//---------------------------------------------------------------------- +// Main for tstfind +// +int main() //short argc, char **argv) +{ + int rslt,cnt; + char return_msg[128]; + int portnum=0; + + // check for required port name + if (argc != 2) + { + printf("1-Wire Net name required on command line!\n" + " (example: \"COM1\" (Win32 DS2480),\"/dev/cua0\" " + "(Linux DS2480),\"1\" (Win32 TMEX)\n"); + exit(1); + } + + // attempt to acquire the 1-Wire Net + if (!owAcquire(portnum,argv[1],return_msg)) + { + printf("%s",return_msg); + exit(1); + } + + // success + printf("%s",return_msg); + + //---------------------------------------- + // Introduction + printf("\n/---------------------------------------------\n"); + printf(" Loop to find all iButton on 1-Wire Net.\n\n"); + + do + { + printf("-------------------- Start of search\n"); + cnt = 0; + + // find the first device (all devices not just alarming) + rslt = owFirst(portnum, TRUE, FALSE); + while (rslt) + { + // print the device number + cnt++; + printf("(%d) ",cnt); + + // print the Serial Number of the device just found + PrintSerialNum(portnum); + + // find the next device + rslt = owNext(portnum, TRUE, FALSE); + } + printf("-------------------- End of search\n\n"); + + } + while (!key_abort()); + + // release the 1-Wire Net + owRelease(portnum,return_msg); + printf("%s",return_msg); + exit(0); + + return 0; +} + +//---------------------------------------------------------------------- +// Read and print the Serial Number. +// +void PrintSerialNum(int portnum) +{ + uchar serial_num[8]; + int i; + + owSerialNum(portnum,serial_num,TRUE); + for (i = 7; i >= 0; i--) + printf("%02X",serial_num[i]); + printf("\n"); +}