Now supports DS18B20 and DS18S20 Maxim/Dallas one-wire thermometer devices. Also supports DS18S20 in 9, 10, 11, and 12 bit resolution modes. 'Use Address' mode now checks if the correct device type is present, and informs the user which device to use. Correct temperature conversion times now used in non-parasitic mode. The device should be placed at least 6 inches (15 cm) from the mbed board in order to accurately read ambient temperature.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers OneWireCRC.cpp Source File

OneWireCRC.cpp

00001 /*
00002 * OneWireCRC. This is a port to mbed of Jim Studt's Adruino One Wire
00003 * library. Please see additional copyrights below this one, including
00004 * references to other copyrights.
00005 *
00006 * Copyright (C) <2009> Petras Saduikis <petras@petras.co.uk>
00007 *
00008 * This file is part of OneWireCRC.
00009 *
00010 * OneWireCRC is free software: you can redistribute it and/or modify
00011 * it under the terms of the GNU General Public License as published by
00012 * the Free Software Foundation, either version 3 of the License, or
00013 * (at your option) any later version.
00014 * 
00015 * OneWireCRC is distributed in the hope that it will be useful,
00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 * GNU General Public License for more details.
00019 *
00020 * You should have received a copy of the GNU General Public License
00021 * along with OneWireCRC.  If not, see <http://www.gnu.org/licenses/>.
00022 */
00023 /*
00024 Copyright (c) 2007, Jim Studt
00025 
00026 Updated to work with arduino-0008 and to include skip() as of
00027 2007/07/06. --RJL20
00028 
00029 Modified to calculate the 8-bit CRC directly, avoiding the need for
00030 the 256-byte lookup table to be loaded in RAM.  Tested in arduino-0010
00031 -- Tom Pollard, Jan 23, 2008
00032 
00033 Permission is hereby granted, free of charge, to any person obtaining
00034 a copy of this software and associated documentation files (the
00035 "Software"), to deal in the Software without restriction, including
00036 without limitation the rights to use, copy, modify, merge, publish,
00037 distribute, sublicense, and/or sell copies of the Software, and to
00038 permit persons to whom the Software is furnished to do so, subject to
00039 the following conditions:
00040 
00041 The above copyright notice and this permission notice shall be
00042 included in all copies or substantial portions of the Software.
00043 
00044 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00045 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00046 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00047 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00048 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00049 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00050 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00051 
00052 Much of the code was inspired by Derek Yerger's code, though I don't
00053 think much of that remains.  In any event that was..
00054     (copyleft) 2006 by Derek Yerger - Free to distribute freely.
00055 
00056 The CRC code was excerpted and inspired by the Dallas Semiconductor 
00057 sample code bearing this copyright.
00058 //---------------------------------------------------------------------------
00059 // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
00060 //
00061 // Permission is hereby granted, free of charge, to any person obtaining a
00062 // copy of this software and associated documentation files (the "Software"),
00063 // to deal in the Software without restriction, including without limitation
00064 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
00065 // and/or sell copies of the Software, and to permit persons to whom the
00066 // Software is furnished to do so, subject to the following conditions:
00067 //
00068 // The above copyright notice and this permission notice shall be included
00069 // in all copies or substantial portions of the Software.
00070 //
00071 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00072 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00073 // MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00074 // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
00075 // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00076 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00077 // OTHER DEALINGS IN THE SOFTWARE.
00078 //
00079 // Except as contained in this notice, the name of Dallas Semiconductor
00080 // shall not be used except as stated in the Dallas Semiconductor
00081 // Branding Policy.
00082 //--------------------------------------------------------------------------
00083 */
00084 
00085 #include "OneWireCRC.h"
00086 #include "OneWireDefs.h"
00087 
00088 // recommended data sheet timings in micro seconds
00089 const int standardT[] = {6, 64, 60, 10, 9, 55, 0, 480, 70, 410};
00090 const int overdriveT[] = {1.5, 7.5, 7.5, 2.5, 0.75, 7, 2.5, 70, 8.5, 40};
00091 
00092 OneWireCRC::OneWireCRC(PinName oneWire, eSpeed speed) : oneWirePort(oneWire)
00093 {
00094     if (STANDARD == speed) timing = standardT;   
00095     else  timing = overdriveT;  // overdrive
00096     
00097     resetSearch();    // reset address search state
00098 }
00099 
00100 // Generate a 1-wire reset, return 1 if no presence detect was found,
00101 // return 0 otherwise.
00102 // (NOTE: does not handle alarm presence from DS2404/DS1994)
00103 int OneWireCRC::reset() 
00104 {
00105     
00106     BYTE result = 0;    // sample presence pulse result
00107         
00108     wait_us(timing[6]);
00109     oneWirePort.output();
00110     oneWirePort = 0;
00111     wait_us(timing[7]);
00112     oneWirePort.input();
00113     wait_us(timing[8]);
00114     result = !(oneWirePort & 0x01);
00115     wait_us(timing[9]);
00116     
00117     return result;
00118 }
00119 
00120 //
00121 // Write a bit. Port and bit is used to cut lookup time and provide
00122 // more certain timing.
00123 //
00124 void OneWireCRC::writeBit(int bit)
00125 {
00126     bit = bit & 0x01;
00127     
00128     if (bit)
00129     {
00130         // Write '1' bit
00131         oneWirePort.output();
00132         oneWirePort = 0;
00133         wait_us(timing[0]);
00134         oneWirePort.input();
00135         wait_us(timing[1]);
00136     }
00137     else
00138     {
00139         // Write '0' bit
00140         oneWirePort.output();
00141         oneWirePort = 0;
00142         wait_us(timing[2]);
00143         oneWirePort.input();
00144         wait_us(timing[3]);
00145     }
00146 }
00147 
00148 //
00149 // Read a bit. Port and bit is used to cut lookup time and provide
00150 // more certain timing.
00151 //
00152 int OneWireCRC::readBit() 
00153 {
00154     BYTE result;
00155     
00156     oneWirePort.output();
00157     oneWirePort = 0;
00158     wait_us(timing[0]);
00159     oneWirePort.input();
00160     wait_us(timing[4]);
00161     result = oneWirePort & 0x01;
00162     wait_us(timing[5]);
00163        
00164     return result;
00165 }
00166 
00167 //
00168 // Write a byte. The writing code uses the active drivers to raise the
00169 // pin high, if you need power after the write (e.g. DS18S20 in
00170 // parasite power mode) then set 'power' to 1, otherwise the pin will
00171 // go tri-state at the end of the write to avoid heating in a short or
00172 // other mishap.
00173 //
00174 void OneWireCRC::writeByte(int data) 
00175 {
00176     // Loop to write each bit in the byte, LS-bit first
00177     for (int loop = 0; loop < 8; loop++)
00178     {
00179         writeBit(data & 0x01);
00180         
00181         // shift the data byte for the next bit
00182         data >>= 1;
00183     }
00184 }
00185 
00186 //
00187 // Read a byte
00188 //
00189 int OneWireCRC::readByte() 
00190 {
00191     int result = 0;
00192     
00193     for (int loop = 0; loop < 8; loop++)
00194     {
00195         // shift the result to get it ready for the next bit
00196         result >>= 1;
00197         
00198         // if result is one, then set MS bit
00199         if (readBit()) result |= 0x80;
00200     }
00201     
00202     return result;
00203 }
00204 
00205 int OneWireCRC::touchByte(int data)
00206 {
00207     int result = 0;
00208     
00209     for (int loop = 0; loop < 8; loop++)
00210     {
00211         // shift the result to get it ready for the next bit
00212         result >>= 1;
00213         
00214         // If sending a '1' then read a bit else write a '0'
00215         if (data & 0x01)
00216         {
00217             if (readBit()) result |= 0x80;
00218         }
00219         else writeBit(0);
00220         
00221         // shift the data byte for the next bit
00222         data >>= 1;
00223     }
00224     
00225     return result;
00226 }
00227 
00228 void OneWireCRC::block(BYTE* data, int data_len)
00229 {
00230     for (int loop = 0; loop < data_len; loop++)
00231     {
00232         data[loop] = touchByte(data[loop]);
00233     }
00234 }
00235 
00236 int OneWireCRC::overdriveSkip(BYTE* data, int data_len)
00237 {
00238     // set the speed to 'standard'
00239     timing = standardT;
00240     
00241     // reset all devices
00242     if (reset()) return 0;    // if no devices found
00243     
00244     // overdrive skip command
00245     writeByte(OVERDRIVE_SKIP);
00246     
00247     // set the speed to 'overdrive'
00248     timing = overdriveT;
00249     
00250     // do a 1-Wire reset in 'overdrive' and return presence result
00251     return reset();
00252 }
00253 
00254 //
00255 // Do a ROM select
00256 //
00257 void OneWireCRC::matchROM(BYTE rom[8])
00258 {
00259     writeByte(MATCH_ROM);         // Choose ROM
00260 
00261     for(int i = 0; i < 8; i++) writeByte(rom[i]);
00262 }
00263 
00264 //
00265 // Do a ROM skip
00266 //
00267 void OneWireCRC::skipROM()
00268 {
00269     writeByte(SKIP_ROM);         // Skip ROM
00270 }
00271 
00272 //
00273 // You need to use this function to start a search again from the beginning.
00274 // You do not need to do it for the first search, though you could.
00275 //
00276 void OneWireCRC::resetSearch()
00277 {
00278     searchJunction = -1;
00279     searchExhausted = false;
00280     for (int i = 0; i < 8; i++) 
00281     {
00282         address[i] = 0;
00283     }
00284 }
00285 
00286 //
00287 // Perform a search. If this function returns a '1' then it has
00288 // enumerated the next device and you may retrieve the ROM from the
00289 // OneWire::address variable. If there are no devices, no further
00290 // devices, or something horrible happens in the middle of the
00291 // enumeration then a 0 is returned.  If a new device is found then
00292 // its address is copied to newAddr.  Use OneWire::reset_search() to
00293 // start over.
00294 // 
00295 BYTE OneWireCRC::search(BYTE* newAddr)
00296 {
00297     BYTE i;
00298     int lastJunction = -1;
00299     BYTE done = 1;
00300     
00301     if (searchExhausted) return 0;
00302     
00303     if (!reset()) return 0;
00304 
00305     writeByte(SEARCH_ROM);
00306     
00307     for(i = 0; i < 64; i++) 
00308     {
00309         BYTE a = readBit( );
00310         BYTE nota = readBit( );
00311         BYTE ibyte = i/8;
00312         BYTE ibit = 1 << (i & 7);
00313     
00314         // I don't think this should happen, this means nothing responded, but maybe if
00315         // something vanishes during the search it will come up.
00316         if (a && nota) return 0;  
00317         
00318         if (!a && !nota)
00319         {
00320             if (i == searchJunction) 
00321             {
00322                 // this is our time to decide differently, we went zero last time, go one.
00323                 a = 1;
00324                 searchJunction = lastJunction;
00325             } 
00326             else if (i < searchJunction) 
00327             {
00328                 // take whatever we took last time, look in address
00329                 if (address[ibyte] & ibit) a = 1;
00330                 else 
00331                 {
00332                     // Only 0s count as pending junctions, we've already exhasuted the 0 side of 1s
00333                     a = 0;
00334                     done = 0;
00335                     lastJunction = i;
00336                 }
00337             } 
00338             else 
00339             {
00340                 // we are blazing new tree, take the 0
00341                 a = 0;
00342                 searchJunction = i;
00343                 done = 0;
00344             }
00345             lastJunction = i;
00346         }
00347         
00348         if (a) address[ibyte] |= ibit;
00349         else address[ibyte] &= ~ibit;
00350     
00351         writeBit(a);
00352     }
00353     
00354     if (done) searchExhausted = true;
00355     
00356     for (i = 0; i < 8; i++) newAddr[i] = address[i];
00357     
00358     return 1;  
00359 }
00360 
00361 // The 1-Wire CRC scheme is described in Maxim Application Note 27:
00362 // "Understanding and Using Cyclic Redundancy Checks with Maxim iButton Products"
00363 //
00364 
00365 #if ONEWIRE_CRC8_TABLE
00366 // This table comes from Dallas sample code where it is freely reusable, 
00367 // though Copyright (C) 2000 Dallas Semiconductor Corporation
00368 static BYTE dscrc_table[] = 
00369 {
00370       0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
00371     157,195, 33,127,252,162, 64, 30, 95,  1,227,189, 62, 96,130,220,
00372      35,125,159,193, 66, 28,254,160,225,191, 93,  3,128,222, 60, 98,
00373     190,224,  2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
00374      70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89,  7,
00375     219,133,103, 57,186,228,  6, 88, 25, 71,165,251,120, 38,196,154,
00376     101, 59,217,135,  4, 90,184,230,167,249, 27, 69,198,152,122, 36,
00377     248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91,  5,231,185,
00378     140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
00379      17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
00380     175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
00381      50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
00382     202,148,118, 40,171,245, 23, 73,  8, 86,180,234,105, 55,213,139,
00383      87,  9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
00384     233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
00385     116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
00386 
00387 //
00388 // Compute a Dallas Semiconductor 8 bit CRC. These show up in the ROM
00389 // and the registers.  (note: this might better be done without the
00390 // table, it would probably be smaller and certainly fast enough
00391 // compared to all those delayMicrosecond() calls.  But I got
00392 // confused, so I use this table from the examples.)  
00393 //
00394 BYTE OneWireCRC::crc8(BYTE* addr, BYTE len)
00395 {
00396     BYTE i;
00397     BYTE crc = 0;
00398     
00399     for (i = 0; i < len; i++)
00400     {
00401         crc  = dscrc_table[crc ^ addr[i] ];
00402     }
00403     
00404     return crc;
00405 }
00406 #else
00407 //
00408 // Compute a Dallas Semiconductor 8 bit CRC directly. 
00409 //
00410 BYTE OneWireCRC::crc8(BYTE* addr, BYTE len)
00411 {
00412     BYTE i, j;
00413     BYTE crc = 0;
00414     
00415     for (i = 0; i < len; i++) 
00416     {
00417         BYTE inbyte = addr[i];
00418         for (j = 0; j < 8; j++) 
00419         {
00420             BYTE mix = (crc ^ inbyte) & 0x01;
00421             crc >>= 1;
00422             if (mix) crc ^= 0x8C;
00423             inbyte >>= 1;
00424         }
00425     }
00426     
00427     return crc;
00428 }
00429 #endif
00430 
00431 static short oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
00432 
00433 //
00434 // Compute a Dallas Semiconductor 16 bit CRC. I have never seen one of
00435 // these, but here it is.
00436 //
00437 unsigned short OneWireCRC::crc16(unsigned short* data, unsigned short len)
00438 {
00439     unsigned short i;
00440     unsigned short crc = 0;
00441     
00442     for ( i = 0; i < len; i++) 
00443     {
00444         unsigned short cdata = data[len];
00445     
00446         cdata = (cdata ^ (crc & 0xff)) & 0xff;
00447         crc >>= 8;
00448     
00449         if (oddparity[cdata & 0xf] ^ oddparity[cdata >> 4]) crc ^= 0xc001;
00450     
00451         cdata <<= 6;
00452         crc ^= cdata;
00453         cdata <<= 1;
00454         crc ^= cdata;
00455     }
00456     
00457     return crc;
00458 }
00459