libraries / OneWire / OneWire.cppon commit Added link to project report (97a3ba0)
   1/*
   2Copyright (c) 2007, Jim Studt  (original old version - many contributors since)
   3
   4The latest version of this library may be found at:
   5  http://www.pjrc.com/teensy/td_libs_OneWire.html
   6
   7OneWire has been maintained by Paul Stoffregen (paul@pjrc.com) since
   8January 2010.  At the time, it was in need of many bug fixes, but had
   9been abandoned the original author (Jim Studt).  None of the known
  10contributors were interested in maintaining OneWire.  Paul typically
  11works on OneWire every 6 to 12 months.  Patches usually wait that
  12long.  If anyone is interested in more actively maintaining OneWire,
  13please contact Paul.
  14
  15Version 2.3:
  16  Unknonw chip fallback mode, Roger Clark
  17  Teensy-LC compatibility, Paul Stoffregen
  18  Search bug fix, Love Nystrom
  19
  20Version 2.2:
  21  Teensy 3.0 compatibility, Paul Stoffregen, paul@pjrc.com
  22  Arduino Due compatibility, http://arduino.cc/forum/index.php?topic=141030
  23  Fix DS18B20 example negative temperature
  24  Fix DS18B20 example's low res modes, Ken Butcher
  25  Improve reset timing, Mark Tillotson
  26  Add const qualifiers, Bertrik Sikken
  27  Add initial value input to crc16, Bertrik Sikken
  28  Add target_search() function, Scott Roberts
  29
  30Version 2.1:
  31  Arduino 1.0 compatibility, Paul Stoffregen
  32  Improve temperature example, Paul Stoffregen
  33  DS250x_PROM example, Guillermo Lovato
  34  PIC32 (chipKit) compatibility, Jason Dangel, dangel.jason AT gmail.com
  35  Improvements from Glenn Trewitt:
  36  - crc16() now works
  37  - check_crc16() does all of calculation/checking work.
  38  - Added read_bytes() and write_bytes(), to reduce tedious loops.
  39  - Added ds2408 example.
  40  Delete very old, out-of-date readme file (info is here)
  41
  42Version 2.0: Modifications by Paul Stoffregen, January 2010:
  43http://www.pjrc.com/teensy/td_libs_OneWire.html
  44  Search fix from Robin James
  45    http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295/27#27
  46  Use direct optimized I/O in all cases
  47  Disable interrupts during timing critical sections
  48    (this solves many random communication errors)
  49  Disable interrupts during read-modify-write I/O
  50  Reduce RAM consumption by eliminating unnecessary
  51    variables and trimming many to 8 bits
  52  Optimize both crc8 - table version moved to flash
  53
  54Modified to work with larger numbers of devices - avoids loop.
  55Tested in Arduino 11 alpha with 12 sensors.
  5626 Sept 2008 -- Robin James
  57http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295/27#27
  58
  59Updated to work with arduino-0008 and to include skip() as of
  602007/07/06. --RJL20
  61
  62Modified to calculate the 8-bit CRC directly, avoiding the need for
  63the 256-byte lookup table to be loaded in RAM.  Tested in arduino-0010
  64-- Tom Pollard, Jan 23, 2008
  65
  66Jim Studt's original library was modified by Josh Larios.
  67
  68Tom Pollard, pollard@alum.mit.edu, contributed around May 20, 2008
  69
  70Permission is hereby granted, free of charge, to any person obtaining
  71a copy of this software and associated documentation files (the
  72"Software"), to deal in the Software without restriction, including
  73without limitation the rights to use, copy, modify, merge, publish,
  74distribute, sublicense, and/or sell copies of the Software, and to
  75permit persons to whom the Software is furnished to do so, subject to
  76the following conditions:
  77
  78The above copyright notice and this permission notice shall be
  79included in all copies or substantial portions of the Software.
  80
  81THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  82EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  83MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  84NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  85LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  86OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  87WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  88
  89Much of the code was inspired by Derek Yerger's code, though I don't
  90think much of that remains.  In any event that was..
  91    (copyleft) 2006 by Derek Yerger - Free to distribute freely.
  92
  93The CRC code was excerpted and inspired by the Dallas Semiconductor
  94sample code bearing this copyright.
  95//---------------------------------------------------------------------------
  96// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
  97//
  98// Permission is hereby granted, free of charge, to any person obtaining a
  99// copy of this software and associated documentation files (the "Software"),
 100// to deal in the Software without restriction, including without limitation
 101// the rights to use, copy, modify, merge, publish, distribute, sublicense,
 102// and/or sell copies of the Software, and to permit persons to whom the
 103// Software is furnished to do so, subject to the following conditions:
 104//
 105// The above copyright notice and this permission notice shall be included
 106// in all copies or substantial portions of the Software.
 107//
 108// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 109// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 110// MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 111// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
 112// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 113// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 114// OTHER DEALINGS IN THE SOFTWARE.
 115//
 116// Except as contained in this notice, the name of Dallas Semiconductor
 117// shall not be used except as stated in the Dallas Semiconductor
 118// Branding Policy.
 119//--------------------------------------------------------------------------
 120*/
 121
 122#include "OneWire.h"
 123
 124
 125OneWire::OneWire(uint8_t pin)
 126{
 127        pinMode(pin, INPUT);
 128        bitmask = PIN_TO_BITMASK(pin);
 129        baseReg = PIN_TO_BASEREG(pin);
 130#if ONEWIRE_SEARCH
 131        reset_search();
 132#endif
 133}
 134
 135
 136// Perform the onewire reset function.  We will wait up to 250uS for
 137// the bus to come high, if it doesn't then it is broken or shorted
 138// and we return a 0;
 139//
 140// Returns 1 if a device asserted a presence pulse, 0 otherwise.
 141//
 142uint8_t OneWire::reset(void)
 143{
 144        IO_REG_TYPE mask = bitmask;
 145        volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;
 146        uint8_t r;
 147        uint8_t retries = 125;
 148
 149        noInterrupts();
 150        DIRECT_MODE_INPUT(reg, mask);
 151        interrupts();
 152        // wait until the wire is high... just in case
 153        do {
 154                if (--retries == 0) return 0;
 155                delayMicroseconds(2);
 156        } while ( !DIRECT_READ(reg, mask));
 157
 158        noInterrupts();
 159        DIRECT_WRITE_LOW(reg, mask);
 160        DIRECT_MODE_OUTPUT(reg, mask);  // drive output low
 161        interrupts();
 162        delayMicroseconds(480);
 163        noInterrupts();
 164        DIRECT_MODE_INPUT(reg, mask);   // allow it to float
 165        delayMicroseconds(70);
 166        r = !DIRECT_READ(reg, mask);
 167        interrupts();
 168        delayMicroseconds(410);
 169        return r;
 170}
 171
 172//
 173// Write a bit. Port and bit is used to cut lookup time and provide
 174// more certain timing.
 175//
 176void OneWire::write_bit(uint8_t v)
 177{
 178        IO_REG_TYPE mask=bitmask;
 179        volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;
 180
 181        if (v & 1) {
 182                noInterrupts();
 183                DIRECT_WRITE_LOW(reg, mask);
 184                DIRECT_MODE_OUTPUT(reg, mask);  // drive output low
 185                delayMicroseconds(10);
 186                DIRECT_WRITE_HIGH(reg, mask);   // drive output high
 187                interrupts();
 188                delayMicroseconds(55);
 189        } else {
 190                noInterrupts();
 191                DIRECT_WRITE_LOW(reg, mask);
 192                DIRECT_MODE_OUTPUT(reg, mask);  // drive output low
 193                delayMicroseconds(65);
 194                DIRECT_WRITE_HIGH(reg, mask);   // drive output high
 195                interrupts();
 196                delayMicroseconds(5);
 197        }
 198}
 199
 200//
 201// Read a bit. Port and bit is used to cut lookup time and provide
 202// more certain timing.
 203//
 204uint8_t OneWire::read_bit(void)
 205{
 206        IO_REG_TYPE mask=bitmask;
 207        volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;
 208        uint8_t r;
 209
 210        noInterrupts();
 211        DIRECT_MODE_OUTPUT(reg, mask);
 212        DIRECT_WRITE_LOW(reg, mask);
 213        delayMicroseconds(3);
 214        DIRECT_MODE_INPUT(reg, mask);   // let pin float, pull up will raise
 215        delayMicroseconds(10);
 216        r = DIRECT_READ(reg, mask);
 217        interrupts();
 218        delayMicroseconds(53);
 219        return r;
 220}
 221
 222//
 223// Write a byte. The writing code uses the active drivers to raise the
 224// pin high, if you need power after the write (e.g. DS18S20 in
 225// parasite power mode) then set 'power' to 1, otherwise the pin will
 226// go tri-state at the end of the write to avoid heating in a short or
 227// other mishap.
 228//
 229void OneWire::write(uint8_t v, uint8_t power /* = 0 */) {
 230    uint8_t bitMask;
 231
 232    for (bitMask = 0x01; bitMask; bitMask <<= 1) {
 233        OneWire::write_bit( (bitMask & v)?1:0);
 234    }
 235    if ( !power) {
 236        noInterrupts();
 237        DIRECT_MODE_INPUT(baseReg, bitmask);
 238        DIRECT_WRITE_LOW(baseReg, bitmask);
 239        interrupts();
 240    }
 241}
 242
 243void OneWire::write_bytes(const uint8_t *buf, uint16_t count, bool power /* = 0 */) {
 244  for (uint16_t i = 0 ; i < count ; i++)
 245    write(buf[i]);
 246  if (!power) {
 247    noInterrupts();
 248    DIRECT_MODE_INPUT(baseReg, bitmask);
 249    DIRECT_WRITE_LOW(baseReg, bitmask);
 250    interrupts();
 251  }
 252}
 253
 254//
 255// Read a byte
 256//
 257uint8_t OneWire::read() {
 258    uint8_t bitMask;
 259    uint8_t r = 0;
 260
 261    for (bitMask = 0x01; bitMask; bitMask <<= 1) {
 262        if ( OneWire::read_bit()) r |= bitMask;
 263    }
 264    return r;
 265}
 266
 267void OneWire::read_bytes(uint8_t *buf, uint16_t count) {
 268  for (uint16_t i = 0 ; i < count ; i++)
 269    buf[i] = read();
 270}
 271
 272//
 273// Do a ROM select
 274//
 275void OneWire::select(const uint8_t rom[8])
 276{
 277    uint8_t i;
 278
 279    write(0x55);           // Choose ROM
 280
 281    for (i = 0; i < 8; i++) write(rom[i]);
 282}
 283
 284//
 285// Do a ROM skip
 286//
 287void OneWire::skip()
 288{
 289    write(0xCC);           // Skip ROM
 290}
 291
 292void OneWire::depower()
 293{
 294        noInterrupts();
 295        DIRECT_MODE_INPUT(baseReg, bitmask);
 296        interrupts();
 297}
 298
 299#if ONEWIRE_SEARCH
 300
 301//
 302// You need to use this function to start a search again from the beginning.
 303// You do not need to do it for the first search, though you could.
 304//
 305void OneWire::reset_search()
 306{
 307  // reset the search state
 308  LastDiscrepancy = 0;
 309  LastDeviceFlag = FALSE;
 310  LastFamilyDiscrepancy = 0;
 311  for(int i = 7; ; i--) {
 312    ROM_NO[i] = 0;
 313    if ( i == 0) break;
 314  }
 315}
 316
 317// Setup the search to find the device type 'family_code' on the next call
 318// to search(*newAddr) if it is present.
 319//
 320void OneWire::target_search(uint8_t family_code)
 321{
 322   // set the search state to find SearchFamily type devices
 323   ROM_NO[0] = family_code;
 324   for (uint8_t i = 1; i < 8; i++)
 325      ROM_NO[i] = 0;
 326   LastDiscrepancy = 64;
 327   LastFamilyDiscrepancy = 0;
 328   LastDeviceFlag = FALSE;
 329}
 330
 331//
 332// Perform a search. If this function returns a '1' then it has
 333// enumerated the next device and you may retrieve the ROM from the
 334// OneWire::address variable. If there are no devices, no further
 335// devices, or something horrible happens in the middle of the
 336// enumeration then a 0 is returned.  If a new device is found then
 337// its address is copied to newAddr.  Use OneWire::reset_search() to
 338// start over.
 339//
 340// --- Replaced by the one from the Dallas Semiconductor web site ---
 341//--------------------------------------------------------------------------
 342// Perform the 1-Wire Search Algorithm on the 1-Wire bus using the existing
 343// search state.
 344// Return TRUE  : device found, ROM number in ROM_NO buffer
 345//        FALSE : device not found, end of search
 346//
 347uint8_t OneWire::search(uint8_t *newAddr, bool search_mode /* = true */)
 348{
 349   uint8_t id_bit_number;
 350   uint8_t last_zero, rom_byte_number, search_result;
 351   uint8_t id_bit, cmp_id_bit;
 352
 353   unsigned char rom_byte_mask, search_direction;
 354
 355   // initialize for search
 356   id_bit_number = 1;
 357   last_zero = 0;
 358   rom_byte_number = 0;
 359   rom_byte_mask = 1;
 360   search_result = 0;
 361
 362   // if the last call was not the last one
 363   if (!LastDeviceFlag)
 364   {
 365      // 1-Wire reset
 366      if (!reset())
 367      {
 368         // reset the search
 369         LastDiscrepancy = 0;
 370         LastDeviceFlag = FALSE;
 371         LastFamilyDiscrepancy = 0;
 372         return FALSE;
 373      }
 374
 375      // issue the search command
 376      if (search_mode == true) {
 377        write(0xF0);   // NORMAL SEARCH
 378      } else {
 379        write(0xEC);   // CONDITIONAL SEARCH
 380      }
 381
 382      // loop to do the search
 383      do
 384      {
 385         // read a bit and its complement
 386         id_bit = read_bit();
 387         cmp_id_bit = read_bit();
 388
 389         // check for no devices on 1-wire
 390         if ((id_bit == 1) && (cmp_id_bit == 1))
 391            break;
 392         else
 393         {
 394            // all devices coupled have 0 or 1
 395            if (id_bit != cmp_id_bit)
 396               search_direction = id_bit;  // bit write value for search
 397            else
 398            {
 399               // if this discrepancy if before the Last Discrepancy
 400               // on a previous next then pick the same as last time
 401               if (id_bit_number < LastDiscrepancy)
 402                  search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
 403               else
 404                  // if equal to last pick 1, if not then pick 0
 405                  search_direction = (id_bit_number == LastDiscrepancy);
 406
 407               // if 0 was picked then record its position in LastZero
 408               if (search_direction == 0)
 409               {
 410                  last_zero = id_bit_number;
 411
 412                  // check for Last discrepancy in family
 413                  if (last_zero < 9)
 414                     LastFamilyDiscrepancy = last_zero;
 415               }
 416            }
 417
 418            // set or clear the bit in the ROM byte rom_byte_number
 419            // with mask rom_byte_mask
 420            if (search_direction == 1)
 421              ROM_NO[rom_byte_number] |= rom_byte_mask;
 422            else
 423              ROM_NO[rom_byte_number] &= ~rom_byte_mask;
 424
 425            // serial number search direction write bit
 426            write_bit(search_direction);
 427
 428            // increment the byte counter id_bit_number
 429            // and shift the mask rom_byte_mask
 430            id_bit_number++;
 431            rom_byte_mask <<= 1;
 432
 433            // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
 434            if (rom_byte_mask == 0)
 435            {
 436                rom_byte_number++;
 437                rom_byte_mask = 1;
 438            }
 439         }
 440      }
 441      while(rom_byte_number < 8);  // loop until through all ROM bytes 0-7
 442
 443      // if the search was successful then
 444      if (!(id_bit_number < 65))
 445      {
 446         // search successful so set LastDiscrepancy,LastDeviceFlag,search_result
 447         LastDiscrepancy = last_zero;
 448
 449         // check for last device
 450         if (LastDiscrepancy == 0)
 451            LastDeviceFlag = TRUE;
 452
 453         search_result = TRUE;
 454      }
 455   }
 456
 457   // if no device found then reset counters so next 'search' will be like a first
 458   if (!search_result || !ROM_NO[0])
 459   {
 460      LastDiscrepancy = 0;
 461      LastDeviceFlag = FALSE;
 462      LastFamilyDiscrepancy = 0;
 463      search_result = FALSE;
 464   } else {
 465      for (int i = 0; i < 8; i++) newAddr[i] = ROM_NO[i];
 466   }
 467   return search_result;
 468  }
 469
 470#endif
 471
 472#if ONEWIRE_CRC
 473// The 1-Wire CRC scheme is described in Maxim Application Note 27:
 474// "Understanding and Using Cyclic Redundancy Checks with Maxim iButton Products"
 475//
 476
 477#if ONEWIRE_CRC8_TABLE
 478// This table comes from Dallas sample code where it is freely reusable,
 479// though Copyright (C) 2000 Dallas Semiconductor Corporation
 480static const uint8_t PROGMEM dscrc_table[] = {
 481      0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
 482    157,195, 33,127,252,162, 64, 30, 95,  1,227,189, 62, 96,130,220,
 483     35,125,159,193, 66, 28,254,160,225,191, 93,  3,128,222, 60, 98,
 484    190,224,  2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
 485     70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89,  7,
 486    219,133,103, 57,186,228,  6, 88, 25, 71,165,251,120, 38,196,154,
 487    101, 59,217,135,  4, 90,184,230,167,249, 27, 69,198,152,122, 36,
 488    248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91,  5,231,185,
 489    140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
 490     17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
 491    175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
 492     50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
 493    202,148,118, 40,171,245, 23, 73,  8, 86,180,234,105, 55,213,139,
 494     87,  9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
 495    233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
 496    116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
 497
 498//
 499// Compute a Dallas Semiconductor 8 bit CRC. These show up in the ROM
 500// and the registers.  (note: this might better be done without to
 501// table, it would probably be smaller and certainly fast enough
 502// compared to all those delayMicrosecond() calls.  But I got
 503// confused, so I use this table from the examples.)
 504//
 505uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len)
 506{
 507        uint8_t crc = 0;
 508
 509        while (len--) {
 510                crc = pgm_read_byte(dscrc_table + (crc ^ *addr++));
 511        }
 512        return crc;
 513}
 514#else
 515//
 516// Compute a Dallas Semiconductor 8 bit CRC directly.
 517// this is much slower, but much smaller, than the lookup table.
 518//
 519uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len)
 520{
 521        uint8_t crc = 0;
 522
 523        while (len--) {
 524#if defined(__AVR__)
 525                crc = _crc_ibutton_update(crc, *addr++);
 526#else
 527                uint8_t inbyte = *addr++;
 528                for (uint8_t i = 8; i; i--) {
 529                        uint8_t mix = (crc ^ inbyte) & 0x01;
 530                        crc >>= 1;
 531                        if (mix) crc ^= 0x8C;
 532                        inbyte >>= 1;
 533                }
 534#endif
 535        }
 536        return crc;
 537}
 538#endif
 539
 540#if ONEWIRE_CRC16
 541bool OneWire::check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc)
 542{
 543    crc = ~crc16(input, len, crc);
 544    return (crc & 0xFF) == inverted_crc[0] && (crc >> 8) == inverted_crc[1];
 545}
 546
 547uint16_t OneWire::crc16(const uint8_t* input, uint16_t len, uint16_t crc)
 548{
 549#if defined(__AVR__)
 550    for (uint16_t i = 0 ; i < len ; i++) {
 551        crc = _crc16_update(crc, input[i]);
 552    }
 553#else
 554    static const uint8_t oddparity[16] =
 555        { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
 556
 557    for (uint16_t i = 0 ; i < len ; i++) {
 558      // Even though we're just copying a byte from the input,
 559      // we'll be doing 16-bit computation with it.
 560      uint16_t cdata = input[i];
 561      cdata = (cdata ^ crc) & 0xff;
 562      crc >>= 8;
 563
 564      if (oddparity[cdata & 0x0F] ^ oddparity[cdata >> 4])
 565          crc ^= 0xC001;
 566
 567      cdata <<= 6;
 568      crc ^= cdata;
 569      cdata <<= 1;
 570      crc ^= cdata;
 571    }
 572#endif
 573    return crc;
 574}
 575#endif
 576
 577#endif