REVO / OneWire

Fork of OneWire by Zoltan Hudak

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers OneWire.cpp Source File

OneWire.cpp

00001 /*
00002 Copyright (c) 2007, Jim Studt  (original old version - many contributors since)
00003 
00004 The latest version of this library may be found at:
00005   http://www.pjrc.com/teensy/td_libs_OneWire.html
00006 
00007 OneWire has been maintained by Paul Stoffregen (paul@pjrc.com) since
00008 January 2010.  At the time, it was in need of many bug fixes, but had
00009 been abandoned the original author (Jim Studt).  None of the known
00010 contributors were interested in maintaining OneWire.  Paul typically
00011 works on OneWire every 6 to 12 months.  Patches usually wait that
00012 long.  If anyone is interested in more actively maintaining OneWire,
00013 please contact Paul.
00014 
00015 Version 2.2:
00016   Teensy 3.0 compatibility, Paul Stoffregen, paul@pjrc.com
00017   Arduino Due compatibility, http://arduino.cc/forum/index.php?topic=141030
00018   Fix DS18B20 example negative temperature
00019   Fix DS18B20 example's low res modes, Ken Butcher
00020   Improve reset timing, Mark Tillotson
00021   Add const qualifiers, Bertrik Sikken
00022   Add initial value input to crc16, Bertrik Sikken
00023   Add target_search() function, Scott Roberts
00024 
00025 Version 2.1:
00026   Arduino 1.0 compatibility, Paul Stoffregen
00027   Improve temperature example, Paul Stoffregen
00028   DS250x_PROM example, Guillermo Lovato
00029   PIC32 (chipKit) compatibility, Jason Dangel, dangel.jason AT gmail.com
00030   Improvements from Glenn Trewitt:
00031   - crc16() now works
00032   - check_crc16() does all of calculation/checking work.
00033   - Added read_bytes() and write_bytes(), to reduce tedious loops.
00034   - Added ds2408 example.
00035   Delete very old, out-of-date readme file (info is here)
00036 
00037 Version 2.0: Modifications by Paul Stoffregen, January 2010:
00038 http://www.pjrc.com/teensy/td_libs_OneWire.html
00039   Search fix from Robin James
00040     http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295/27#27
00041   Use direct optimized I/O in all cases
00042   Disable interrupts during timing critical sections
00043     (this solves many random communication errors)
00044   Disable interrupts during read-modify-write I/O
00045   Reduce RAM consumption by eliminating unnecessary
00046     variables and trimming many to 8 bits
00047   Optimize both crc8 - table version moved to flash
00048 
00049 Modified to work with larger numbers of devices - avoids loop.
00050 Tested in Arduino 11 alpha with 12 sensors.
00051 26 Sept 2008 -- Robin James
00052 http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295/27#27
00053 
00054 Updated to work with arduino-0008 and to include skip() as of
00055 2007/07/06. --RJL20
00056 
00057 Modified to calculate the 8-bit CRC directly, avoiding the need for
00058 the 256-byte lookup table to be loaded in RAM.  Tested in arduino-0010
00059 -- Tom Pollard, Jan 23, 2008
00060 
00061 Jim Studt's original library was modified by Josh Larios.
00062 
00063 Tom Pollard, pollard@alum.mit.edu, contributed around May 20, 2008
00064 
00065 Permission is hereby granted, free of charge, to any person obtaining
00066 a copy of this software and associated documentation files (the
00067 "Software"), to deal in the Software without restriction, including
00068 without limitation the rights to use, copy, modify, merge, publish,
00069 distribute, sublicense, and/or sell copies of the Software, and to
00070 permit persons to whom the Software is furnished to do so, subject to
00071 the following conditions:
00072 
00073 The above copyright notice and this permission notice shall be
00074 included in all copies or substantial portions of the Software.
00075 
00076 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00077 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00078 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00079 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00080 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00081 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00082 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00083 
00084 Much of the code was inspired by Derek Yerger's code, though I don't
00085 think much of that remains.  In any event that was..
00086     (copyleft) 2006 by Derek Yerger - Free to distribute freely.
00087 
00088 The CRC code was excerpted and inspired by the Dallas Semiconductor
00089 sample code bearing this copyright.
00090 //---------------------------------------------------------------------------
00091 // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
00092 //
00093 // Permission is hereby granted, free of charge, to any person obtaining a
00094 // copy of this software and associated documentation files (the "Software"),
00095 // to deal in the Software without restriction, including without limitation
00096 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
00097 // and/or sell copies of the Software, and to permit persons to whom the
00098 // Software is furnished to do so, subject to the following conditions:
00099 //
00100 // The above copyright notice and this permission notice shall be included
00101 // in all copies or substantial portions of the Software.
00102 //
00103 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00104 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00105 // MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00106 // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
00107 // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00108 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00109 // OTHER DEALINGS IN THE SOFTWARE.
00110 //
00111 // Except as contained in this notice, the name of Dallas Semiconductor
00112 // shall not be used except as stated in the Dallas Semiconductor
00113 // Branding Policy.
00114 //--------------------------------------------------------------------------
00115 */
00116 
00117 #include "OneWire.h"
00118 
00119 OneWire::OneWire(PinName pin):
00120     wire(pin)
00121 {   
00122 #if ONEWIRE_SEARCH
00123     reset_search();
00124 #endif
00125 }
00126 
00127 
00128 // Perform the onewire reset function.  We will wait up to 250uS for
00129 // the bus to come high, if it doesn't then it is broken or shorted
00130 // and we return a 0;
00131 //
00132 // Returns ONEWIRE_OK if a device asserted a presence pulse, ONEWIRE_ERROR otherwise.
00133 //
00134 
00135 
00136 uint8_t OneWire::init_sequence() 
00137 {
00138     uint16_t retries = 20000;
00139     
00140     //if( reset() != ONEWIRE_OK )
00141     //    return ONEWIRE_ERROR;
00142     
00143     reset();
00144         
00145     //wire.input(); should be input coming out of reset    
00146 
00147     wait_us(80);
00148     
00149     while( wire == 0 )
00150     {
00151         if (--retries == 0) {
00152             return ONEWIRE_NO_RESPONSE;   
00153         }
00154         wait_us(20);
00155     }
00156     
00157     return ONEWIRE_OK;
00158 
00159 
00160     
00161     
00162 }
00163     
00164 uint8_t OneWire::reset( bool force/* = true*/ )
00165 {
00166    /*uint8_t retries = 125;
00167 
00168    wire.input();
00169    // wait until the wire is high... just in case
00170    
00171    do {
00172         if (--retries == 0) 
00173         {
00174             if( force )
00175                 break;
00176             else
00177                 return ONEWIRE_ERROR;
00178         }
00179         wait_us(2);
00180     } while (wire != 1);*/
00181 
00182     wire.output();
00183     wire = 0;
00184     wait_us(480);
00185     wire.input();
00186 
00187     //wait_us(70);
00188     /*uint8_t err = wire;     //just do the reset, use init_seq function to do more
00189     
00190     wait_us(240);
00191     if ( wire == 0 )    {    // short circuit
00192         printf("OneWire::reset SHORT_CIRCUIT\r\n");
00193         return ONEWIRE_ERROR_SHORT_CIRCUIT;
00194     }*/
00195     
00196     //printf("OneWire::reset OK\r\n");
00197     return ONEWIRE_OK;
00198 }
00199 
00200 //
00201 // Write a bit. Port and bit is used to cut lookup time and provide
00202 // more certain timing.
00203 //
00204 void OneWire::write_bit(uint8_t v)
00205 {
00206     wire.output();   
00207     
00208     if (v & 1) {
00209         wire = 0;   // drive output low
00210         wait_us(10);
00211         wire = 1;   // drive output high
00212         wait_us(55);
00213     } else {
00214         wire = 0;   // drive output low
00215         wait_us(65);
00216         wire = 1;   // drive output high
00217         wait_us(5);
00218     }
00219 }
00220 
00221 //
00222 // Read a bit. Port and bit is used to cut lookup time and provide
00223 // more certain timing.
00224 //
00225 uint8_t OneWire::read_bit(void)
00226 {
00227     uint8_t r;
00228 
00229     wire.output();
00230     wire = 0;
00231     wait_us(2); //modified to meet ray's values
00232     wire.input();
00233     wait_us(14);    
00234     r = wire.read();   
00235     wait_us(48);
00236     
00237     return r;
00238 }
00239 
00240 //
00241 // Write a byte. The writing code uses the active drivers to raise the
00242 // pin high, if you need power after the write (e.g. DS18S20 in
00243 // parasite power mode) then set 'power' to 1, otherwise the pin will
00244 // go tri-state at the end of the write to avoid heating in a short or
00245 // other mishap.
00246 //
00247 void OneWire::write(uint8_t v, uint8_t power /* = 0 */) {
00248     uint8_t bitMask;
00249     
00250     //printf("OneWire::write => %#x\r\n", v);
00251 
00252     for (bitMask = 0x01; bitMask; bitMask <<= 1) {
00253         OneWire::write_bit( (bitMask & v)?1:0);
00254     }
00255     if ( !power) {
00256         wire.input();
00257     }
00258 }
00259 
00260 void OneWire::write_bytes(const uint8_t *buf, uint16_t count, bool power /* = 0 */) {
00261     
00262     for (uint16_t i = 0 ; i < count ; i++)
00263     {
00264         write(buf[i]);
00265     }
00266     
00267     if (!power) {
00268         wire.input();
00269     }
00270 }
00271 
00272 //
00273 // Read a byte
00274 //
00275 uint8_t OneWire::read() {
00276     uint8_t bitMask;
00277     uint8_t r = 0;
00278 
00279     for (bitMask = 0x01; bitMask; bitMask <<= 1) 
00280     {
00281         if ( OneWire::read_bit()) r |= bitMask;
00282     }
00283     
00284     return r;
00285 }
00286 
00287 void OneWire::read_bytes(uint8_t *buf, uint16_t count) {
00288     for (uint16_t i = 0 ; i < count ; i++)
00289     {
00290         buf[i] = read();
00291     }
00292 }
00293 
00294 //
00295 // Do a ROM select
00296 //
00297 void OneWire::select(const uint8_t rom[8])
00298 {
00299     uint8_t i;
00300 
00301     write(0x55);           // Choose ROM
00302 
00303     for (i = 0; i < 8; i++) write(rom[i]);
00304 }
00305 
00306 //
00307 // Do a ROM skip
00308 //
00309 void OneWire::skip()
00310 {
00311     write(0xCC);           // Skip ROM
00312 }
00313 
00314 void OneWire::depower()
00315 {
00316     wire.input();
00317 }
00318 
00319 #if ONEWIRE_SEARCH
00320 
00321 //
00322 // You need to use this function to start a search again from the beginning.
00323 // You do not need to do it for the first search, though you could.
00324 //
00325 void OneWire::reset_search()
00326 {
00327   // reset the search state
00328   LastDiscrepancy = 0;
00329   LastDeviceFlag = false;
00330   LastFamilyDiscrepancy = 0;
00331   for(int i = 7; ; i--) {
00332     ROM_NO[i] = 0;
00333     if ( i == 0) break;
00334   }
00335 }
00336 
00337 // Setup the search to find the device type 'family_code' on the next call
00338 // to search(*newAddr) if it is present.
00339 //
00340 void OneWire::target_search(uint8_t family_code)
00341 {
00342    // set the search state to find SearchFamily type devices
00343    ROM_NO[0] = family_code;
00344    for (uint8_t i = 1; i < 8; i++)
00345       ROM_NO[i] = 0;
00346    LastDiscrepancy = 64;
00347    LastFamilyDiscrepancy = 0;
00348    LastDeviceFlag = false;
00349 }
00350 
00351 //
00352 // Perform a search. If this function returns a '1' then it has
00353 // enumerated the next device and you may retrieve the ROM from the
00354 // OneWire::address variable. If there are no devices, no further
00355 // devices, or something horrible happens in the middle of the
00356 // enumeration then a 0 is returned.  If a new device is found then
00357 // its address is copied to newAddr.  Use OneWire::reset_search() to
00358 // start over.
00359 //
00360 // --- Replaced by the one from the Dallas Semiconductor web site ---
00361 //--------------------------------------------------------------------------
00362 // Perform the 1-Wire Search Algorithm on the 1-Wire bus using the existing
00363 // search state.
00364 // Return true  : device found, ROM number in ROM_NO buffer
00365 //        false : device not found, end of search
00366 //
00367 uint8_t OneWire::search(uint8_t *newAddr)
00368 {
00369    uint8_t id_bit_number;
00370    uint8_t last_zero, rom_byte_number, search_result;
00371    uint8_t id_bit, cmp_id_bit;
00372 
00373    unsigned char rom_byte_mask, search_direction;
00374 
00375    // initialize for search
00376    id_bit_number = 1;
00377    last_zero = 0;
00378    rom_byte_number = 0;
00379    rom_byte_mask = 1;
00380    search_result = 0;
00381 
00382    // if the last call was not the last one
00383    if (!LastDeviceFlag)
00384    {
00385       // 1-Wire reset
00386       if (!reset())
00387       {
00388          // reset the search
00389          LastDiscrepancy = 0;
00390          LastDeviceFlag = false;
00391          LastFamilyDiscrepancy = 0;
00392          return false;
00393       }
00394 
00395       // issue the search command
00396       write(0xF0);
00397 
00398       // loop to do the search
00399       do
00400       {
00401          // read a bit and its complement
00402          id_bit = read_bit();
00403          cmp_id_bit = read_bit();
00404 
00405          // check for no devices on 1-wire
00406          if ((id_bit == 1) && (cmp_id_bit == 1))
00407             break;
00408          else
00409          {
00410             // all devices coupled have 0 or 1
00411             if (id_bit != cmp_id_bit)
00412                search_direction = id_bit;  // bit write value for search
00413             else
00414             {
00415                // if this discrepancy if before the Last Discrepancy
00416                // on a previous next then pick the same as last time
00417                if (id_bit_number < LastDiscrepancy)
00418                   search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
00419                else
00420                   // if equal to last pick 1, if not then pick 0
00421                   search_direction = (id_bit_number == LastDiscrepancy);
00422 
00423                // if 0 was picked then record its position in LastZero
00424                if (search_direction == 0)
00425                {
00426                   last_zero = id_bit_number;
00427 
00428                   // check for Last discrepancy in family
00429                   if (last_zero < 9)
00430                      LastFamilyDiscrepancy = last_zero;
00431                }
00432             }
00433 
00434             // set or clear the bit in the ROM byte rom_byte_number
00435             // with mask rom_byte_mask
00436             if (search_direction == 1)
00437               ROM_NO[rom_byte_number] |= rom_byte_mask;
00438             else
00439               ROM_NO[rom_byte_number] &= ~rom_byte_mask;
00440 
00441             // serial number search direction write bit
00442             write_bit(search_direction);
00443 
00444             // increment the byte counter id_bit_number
00445             // and shift the mask rom_byte_mask
00446             id_bit_number++;
00447             rom_byte_mask <<= 1;
00448 
00449             // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
00450             if (rom_byte_mask == 0)
00451             {
00452                 rom_byte_number++;
00453                 rom_byte_mask = 1;
00454             }
00455          }
00456       }
00457       while(rom_byte_number < 8);  // loop until through all ROM bytes 0-7
00458 
00459       // if the search was successful then
00460       if (!(id_bit_number < 65))
00461       {
00462          // search successful so set LastDiscrepancy,LastDeviceFlag,search_result
00463          LastDiscrepancy = last_zero;
00464 
00465          // check for last device
00466          if (LastDiscrepancy == 0)
00467             LastDeviceFlag = true;
00468 
00469          search_result = true;
00470       }
00471    }
00472 
00473    // if no device found then reset counters so next 'search' will be like a first
00474    if (!search_result || !ROM_NO[0])
00475    {
00476       LastDiscrepancy = 0;
00477       LastDeviceFlag = false;
00478       LastFamilyDiscrepancy = 0;
00479       search_result = false;
00480    }
00481    for (int i = 0; i < 8; i++) newAddr[i] = ROM_NO[i];
00482    return search_result;
00483   }
00484 
00485 #endif
00486 
00487 #if ONEWIRE_CRC
00488 // The 1-Wire CRC scheme is described in Maxim Application Note 27:
00489 // "Understanding and Using Cyclic Redundancy Checks with Maxim iButton Products"
00490 // Compute a Dallas Semiconductor 8 bit CRC directly.
00491 //
00492 uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len)
00493 {
00494     uint8_t crc = 0;
00495     
00496     while (len--) {
00497         uint8_t inbyte = *addr++;
00498         for (uint8_t i = 8; i; i--) {
00499             uint8_t mix = (crc ^ inbyte) & 0x01;
00500             crc >>= 1;
00501             if (mix) crc ^= 0x8C;
00502             inbyte >>= 1;
00503         }
00504     }
00505     return crc;
00506 }
00507 #endif