Extended MaximInterface

Dependents:   mbed_DS28EC20_GPIO

Files at this revision

API Documentation at this revision

Comitter:
IanBenzMaxim
Date:
Mon Nov 06 14:39:18 2017 -0600
Child:
1:d6de0a14c777
Commit message:
Initial commit.

Changed in this revision

Devices/DS18B20.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS18B20.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS1920.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS1920.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS2413.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS2413.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS2431.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS2431.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS2465.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS2465.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS2480B.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS2480B.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS2482_DS2484.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS2482_DS2484.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS28C36_DS2476.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS28C36_DS2476.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS28E15_22_25.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS28E15_22_25.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS28E17.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS28E17.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS9400.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS9400.hpp Show annotated file Show diff for this revision Revisions of this file
Links/I2CMaster.cpp Show annotated file Show diff for this revision Revisions of this file
Links/I2CMaster.hpp Show annotated file Show diff for this revision Revisions of this file
Links/I2CMasterDecorator.cpp Show annotated file Show diff for this revision Revisions of this file
Links/I2CMasterDecorator.hpp Show annotated file Show diff for this revision Revisions of this file
Links/LoggingI2CMaster.cpp Show annotated file Show diff for this revision Revisions of this file
Links/LoggingI2CMaster.hpp Show annotated file Show diff for this revision Revisions of this file
Links/LoggingOneWireMaster.cpp Show annotated file Show diff for this revision Revisions of this file
Links/LoggingOneWireMaster.hpp Show annotated file Show diff for this revision Revisions of this file
Links/LoggingSleep.cpp Show annotated file Show diff for this revision Revisions of this file
Links/LoggingSleep.hpp Show annotated file Show diff for this revision Revisions of this file
Links/OneWireMaster.cpp Show annotated file Show diff for this revision Revisions of this file
Links/OneWireMaster.hpp Show annotated file Show diff for this revision Revisions of this file
Links/OneWireMasterDecorator.cpp Show annotated file Show diff for this revision Revisions of this file
Links/OneWireMasterDecorator.hpp Show annotated file Show diff for this revision Revisions of this file
Links/RomCommands.cpp Show annotated file Show diff for this revision Revisions of this file
Links/RomCommands.hpp Show annotated file Show diff for this revision Revisions of this file
Links/SelectRom.cpp Show annotated file Show diff for this revision Revisions of this file
Links/SelectRom.hpp Show annotated file Show diff for this revision Revisions of this file
Links/Sleep.hpp Show annotated file Show diff for this revision Revisions of this file
Links/SleepDecorator.cpp Show annotated file Show diff for this revision Revisions of this file
Links/SleepDecorator.hpp Show annotated file Show diff for this revision Revisions of this file
Links/Uart.cpp Show annotated file Show diff for this revision Revisions of this file
Links/Uart.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterface.vcxproj Show annotated file Show diff for this revision Revisions of this file
MaximInterface.vcxproj.filters Show annotated file Show diff for this revision Revisions of this file
Platforms/dotnet/.mbedignore Show annotated file Show diff for this revision Revisions of this file
Platforms/dotnet/ChangeSizeType.hpp Show annotated file Show diff for this revision Revisions of this file
Platforms/dotnet/DS9481P_300.cpp Show annotated file Show diff for this revision Revisions of this file
Platforms/dotnet/DS9481P_300.hpp Show annotated file Show diff for this revision Revisions of this file
Platforms/dotnet/DelegateWrapper.hpp Show annotated file Show diff for this revision Revisions of this file
Platforms/dotnet/MoveOnly.hpp Show annotated file Show diff for this revision Revisions of this file
Platforms/dotnet/OneWireLinkLayerMaster.cpp Show annotated file Show diff for this revision Revisions of this file
Platforms/dotnet/OneWireLinkLayerMaster.hpp Show annotated file Show diff for this revision Revisions of this file
Platforms/dotnet/Sleep.cpp Show annotated file Show diff for this revision Revisions of this file
Platforms/dotnet/Sleep.hpp Show annotated file Show diff for this revision Revisions of this file
Platforms/dotnet/Uart.cpp Show annotated file Show diff for this revision Revisions of this file
Platforms/dotnet/Uart.hpp Show annotated file Show diff for this revision Revisions of this file
Platforms/mbed/I2CMaster.cpp Show annotated file Show diff for this revision Revisions of this file
Platforms/mbed/I2CMaster.hpp Show annotated file Show diff for this revision Revisions of this file
Platforms/mbed/Sleep.cpp Show annotated file Show diff for this revision Revisions of this file
Platforms/mbed/Sleep.hpp Show annotated file Show diff for this revision Revisions of this file
Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/GpioOneWireMaster.cpp Show annotated file Show diff for this revision Revisions of this file
Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/GpioOneWireMaster.hpp Show annotated file Show diff for this revision Revisions of this file
Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_ARM_STD/owlink.s Show annotated file Show diff for this revision Revisions of this file
Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_GCC_ARM/owlink.S Show annotated file Show diff for this revision Revisions of this file
Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_IAR/owlink.s Show annotated file Show diff for this revision Revisions of this file
Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/owlink.h Show annotated file Show diff for this revision Revisions of this file
Platforms/mbed/Uart.cpp Show annotated file Show diff for this revision Revisions of this file
Platforms/mbed/Uart.hpp Show annotated file Show diff for this revision Revisions of this file
Platforms/mxc/.mbedignore Show annotated file Show diff for this revision Revisions of this file
Platforms/mxc/Error.cpp Show annotated file Show diff for this revision Revisions of this file
Platforms/mxc/Error.hpp Show annotated file Show diff for this revision Revisions of this file
Platforms/mxc/I2CMaster.cpp Show annotated file Show diff for this revision Revisions of this file
Platforms/mxc/I2CMaster.hpp Show annotated file Show diff for this revision Revisions of this file
Platforms/mxc/OneWireMaster.cpp Show annotated file Show diff for this revision Revisions of this file
Platforms/mxc/OneWireMaster.hpp Show annotated file Show diff for this revision Revisions of this file
Platforms/mxc/Sleep.cpp Show annotated file Show diff for this revision Revisions of this file
Platforms/mxc/Sleep.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/Ecc256.cpp Show annotated file Show diff for this revision Revisions of this file
Utilities/Ecc256.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/Error.cpp Show annotated file Show diff for this revision Revisions of this file
Utilities/Error.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/Export.h Show annotated file Show diff for this revision Revisions of this file
Utilities/FlagSet.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/Function.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/HexConversions.cpp Show annotated file Show diff for this revision Revisions of this file
Utilities/HexConversions.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/ManId.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/RomId.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/Segment.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/Sha256.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/Uncopyable.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/WriteMessage.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/array.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/crc.cpp Show annotated file Show diff for this revision Revisions of this file
Utilities/crc.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/system_error.cpp Show annotated file Show diff for this revision Revisions of this file
Utilities/system_error.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/type_traits.hpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS18B20.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,256 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <MaximInterface/Links/OneWireMaster.hpp>
+#include <MaximInterface/Utilities/Error.hpp>
+#include "DS18B20.hpp"
+
+namespace MaximInterface {
+
+enum DS18B20_CMDS {
+  WRITE_SCRATCHPAD = 0x4E,
+  READ_SCRATCHPAD = 0xBE,
+  COPY_SCRATCHPAD = 0x48,
+  CONV_TEMPERATURE = 0x44,
+  READ_POWER_SUPPY = 0xB4,
+  RECALL = 0xB8
+};
+
+error_code DS18B20::initialize() {
+  Scratchpad scratchpad;
+  return readScratchpad(scratchpad);
+}
+
+error_code DS18B20::writeScratchpad(uint_least8_t th, uint_least8_t tl,
+                                    uint_least8_t res) {
+  error_code result = selectRom(*master);
+  if (!result) {
+    const uint_least8_t sendBlock[] = {WRITE_SCRATCHPAD, th, tl, res};
+    result =
+        master->writeBlock(sendBlock, sizeof(sendBlock) / sizeof(sendBlock[0]));
+    if (!result) {
+      resolution = res;
+    }
+  }
+  return result;
+}
+
+error_code DS18B20::readScratchpad(Scratchpad & scratchpad) {
+  error_code result = selectRom(*master);
+  if (result) {
+    return result;
+  }
+  result =
+      master->writeByteSetLevel(READ_SCRATCHPAD, OneWireMaster::NormalLevel);
+  if (result) {
+    return result;
+  }
+  result = master->readBlock(scratchpad.data(), scratchpad.size());
+  if (result) {
+    return result;
+  }
+  uint_least8_t receivedCrc;
+  result = master->readByte(receivedCrc);
+  if (result) {
+    return result;
+  }
+  if (receivedCrc == calculateCrc8(scratchpad.data(), scratchpad.size())) {
+    resolution = scratchpad[4];
+  } else {
+    result = make_error_code(CrcError);
+  }
+  return result;
+}
+
+error_code DS18B20::readPowerSupply(bool & localPower) {
+  error_code result = selectRom(*master);
+  if (result) {
+    return result;
+  }
+  result =
+      master->writeByteSetLevel(READ_POWER_SUPPY, OneWireMaster::NormalLevel);
+  if (result) {
+    return result;
+  }
+  result = master->touchBitSetLevel(localPower, OneWireMaster::NormalLevel);
+  return result;
+}
+
+error_code DS18B20::copyScratchpad() {
+  bool hasLocalPower;
+  error_code result = readPowerSupply(hasLocalPower);
+  if (result) {
+    return result;
+  }
+  result = selectRom(*master);
+  if (result) {
+    return result;
+  }
+  if (hasLocalPower) {
+    result =
+        master->writeByteSetLevel(COPY_SCRATCHPAD, OneWireMaster::NormalLevel);
+    bool recvbit = 0;
+    while (!recvbit && !result) {
+      result = master->touchBitSetLevel(recvbit, OneWireMaster::NormalLevel);
+    }
+  } else {
+    result =
+        master->writeByteSetLevel(COPY_SCRATCHPAD, OneWireMaster::StrongLevel);
+    if (!result) {
+      (*sleep)(10);
+      result = master->setLevel(OneWireMaster::NormalLevel);
+    }
+  }
+  return result;
+}
+
+error_code DS18B20::convertTemperature() {
+  bool hasLocalPower;
+  error_code result = readPowerSupply(hasLocalPower);
+  if (result) {
+    return result;
+  }
+  result = selectRom(*master);
+  if (result) {
+    return result;
+  }
+  if (hasLocalPower) {
+    result =
+        master->writeByteSetLevel(CONV_TEMPERATURE, OneWireMaster::NormalLevel);
+    bool recvbit = 0;
+    while (!result && !recvbit) {
+      result = master->touchBitSetLevel(recvbit, OneWireMaster::NormalLevel);
+    }
+  } else {
+    result =
+        master->writeByteSetLevel(CONV_TEMPERATURE, OneWireMaster::StrongLevel);
+    if (!result) {
+      int sleepTime;
+      switch (resolution) {
+      case nineBitResolution:
+        sleepTime = 94;
+        break;
+
+      case tenBitResolution:
+        sleepTime = 188;
+        break;
+
+      case elevenBitResolution:
+        sleepTime = 375;
+        break;
+
+      case twelveBitResolution:
+      default:
+        sleepTime = 750;
+        break;
+      }
+      (*sleep)(sleepTime);
+      result = master->setLevel(OneWireMaster::NormalLevel);
+    }
+  }
+  return result;
+}
+
+error_code DS18B20::recallEeprom() {
+  error_code result = selectRom(*master);
+  if (!result) {
+    result = master->writeByte(RECALL);
+  }
+  return result;
+}
+
+const error_category & DS18B20::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "DS18B20"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case CrcError:
+        return "CRC Error";
+
+      case DataError:
+        return "Data Error";
+
+      default:
+        return defaultErrorMessage(condition);
+      }
+    }
+  } instance;
+  return instance;
+}
+
+error_code readTemperature(DS18B20 & ds18b20, int & temperature) {
+  error_code result = ds18b20.convertTemperature();
+  if (result) {
+    return result;
+  }
+  DS18B20::Scratchpad scratchpad;
+  result = ds18b20.readScratchpad(scratchpad);
+  if (result) {
+    return result;
+  }
+
+  unsigned int tempData =
+      (static_cast<unsigned int>(scratchpad[1]) << 8) | scratchpad[0];
+  const unsigned int signMask = 0xF800;
+  if ((tempData & signMask) == signMask) {
+    temperature = -0x800;
+  } else if ((tempData & signMask) == 0) {
+    temperature = 0;
+  } else {
+    return make_error_code(DS18B20::DataError);
+  }
+  unsigned int precisionMask;
+  switch (scratchpad[4]) {
+  case DS18B20::nineBitResolution:
+  default:
+    precisionMask = 0x7;
+    break;
+
+  case DS18B20::tenBitResolution:
+    precisionMask = 0x3;
+    break;
+
+  case DS18B20::elevenBitResolution:
+    precisionMask = 0x1;
+    break;
+
+  case DS18B20::twelveBitResolution:
+    precisionMask = 0x0;
+    break;
+  }
+  temperature += static_cast<int>(tempData & ~(signMask | precisionMask));
+  return error_code();
+}
+
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS18B20.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,136 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_DS18B20
+#define MaximInterface_DS18B20
+
+#include <MaximInterface/Links/SelectRom.hpp>
+#include <MaximInterface/Links/Sleep.hpp>
+#include <MaximInterface/Utilities/Export.h>
+
+namespace MaximInterface {
+
+/// DS18B20 Programmable Resolution 1-Wire Digital Thermometer
+/// @details The DS18B20 digital thermometer provides 9-bit to 12-bit
+/// Celsius temperature measurements and has an alarm function with
+/// nonvolatile user-programmable upper and lower trigger points. The
+/// DS18B20 communicates over a 1-Wire bus that by definition requires
+/// only one data line (and ground) for communication with a central
+/// microprocessor. In addition, the DS18B20 can derive power directly
+/// from the data line ("parasite power"), eliminating the need for an
+/// external power supply.
+class DS18B20 {
+public:
+  enum ErrorValue { CrcError = 1, DataError };
+
+  static const uint_least8_t nineBitResolution = 0x1F;
+  static const uint_least8_t tenBitResolution = 0x3F;
+  static const uint_least8_t elevenBitResolution = 0x5F;
+  static const uint_least8_t twelveBitResolution = 0x7F;
+
+  /// Holds the contents of the device scratchpad.
+  typedef array<uint_least8_t, 8> Scratchpad;
+
+  DS18B20(const Sleep & sleep, OneWireMaster & master,
+          const SelectRom & selectRom)
+      : selectRom(selectRom), master(&master), sleep(&sleep), resolution(0) {}
+
+  void setSleep(const Sleep & sleep) { this->sleep = &sleep; }
+  void setMaster(OneWireMaster & master) { this->master = &master; }
+  void setSelectRom(const SelectRom & selectRom) {
+    this->selectRom = selectRom;
+  }
+
+  /// Initializes the device for first time use.
+  MaximInterface_EXPORT error_code initialize();
+
+  /// Write Scratchpad Command
+  /// @details If the result of a temperature measurement is higher
+  /// than TH or lower than TL, an alarm flag inside the device is
+  /// set. This flag is updated with every temperature measurement.
+  /// As long as the alarm flag is set, the DS1920 will respond to
+  /// the alarm search command.
+  /// @param[in] th 8-bit upper temperature threshold, MSB indicates sign.
+  /// @param[in] tl 8-bit lower temperature threshold, LSB indicates sign.
+  /// @param[in] res Resolution of the DS18B20.
+  MaximInterface_EXPORT error_code writeScratchpad(uint_least8_t th,
+                                                   uint_least8_t tl,
+                                                   uint_least8_t res);
+
+  /// Read Scratchpad Command
+  /// @param[out] scratchpad Contents of scratchpad.
+  MaximInterface_EXPORT error_code readScratchpad(Scratchpad & scratchpad);
+
+  /// Copy Scratchpad Command
+  /// @details This command copies from the scratchpad into the
+  /// EEPROM of the DS18B20, storing the temperature trigger bytes
+  /// and resolution in nonvolatile memory.
+  MaximInterface_EXPORT error_code copyScratchpad();
+
+  /// Read Power Supply command
+  /// @details This command determines if the DS18B20 is parasite
+  /// powered or has a local supply
+  /// @param[out] localPower
+  /// True if the device is powered by a local power supply, or false if the
+  /// device is parasitically powered.
+  MaximInterface_EXPORT error_code readPowerSupply(bool & localPower);
+
+  /// Convert Temperature Command
+  /// @details This command begins a temperature conversion.
+  MaximInterface_EXPORT error_code convertTemperature();
+
+  /// Recall Command
+  /// @details This command recalls the temperature trigger values
+  /// and resolution stored in EEPROM to the scratchpad.
+  MaximInterface_EXPORT error_code recallEeprom();
+
+  MaximInterface_EXPORT static const error_category & errorCategory();
+
+private:
+  SelectRom selectRom;
+  OneWireMaster * master;
+  const Sleep * sleep;
+  uint_least8_t resolution;
+};
+
+/// Reads the current temperature as an integer value with decimal.
+/// @param[out] temperature Temperature in degrees Celsius multiplied by 2.
+MaximInterface_EXPORT error_code readTemperature(DS18B20 & ds18b20,
+                                                 int & temperature);
+
+inline error_code make_error_code(DS18B20::ErrorValue e) {
+  return error_code(e, DS18B20::errorCategory());
+}
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS1920.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,157 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <MaximInterface/Links/OneWireMaster.hpp>
+#include <MaximInterface/Utilities/Error.hpp>
+#include "DS1920.hpp"
+
+namespace MaximInterface {
+
+enum DS1920_CMDS {
+  WRITE_SCRATCHPAD = 0x4E,
+  READ_SCRATCHPAD = 0xBE,
+  COPY_SCRATCHPAD = 0x48,
+  CONV_TEMPERATURE = 0x44,
+  RECALL = 0xB8
+};
+
+error_code DS1920::writeScratchpad(uint_least8_t th, uint_least8_t tl) {
+  error_code result = selectRom(*master);
+  if (!result) {
+    const uint_least8_t sendBlock[] = {WRITE_SCRATCHPAD, th, tl};
+    result =
+        master->writeBlock(sendBlock, sizeof(sendBlock) / sizeof(sendBlock[0]));
+  }
+  return result;
+}
+
+error_code DS1920::readScratchpad(Scratchpad & scratchpad) {
+  error_code result = selectRom(*master);
+  if (!result) {
+    result = master->writeByte(READ_SCRATCHPAD);
+    if (!result) {
+      result = master->readBlock(scratchpad.data(), scratchpad.size());
+      if (!result) {
+        uint_least8_t receivedCrc;
+        result = master->readByte(receivedCrc);
+        if (!result && (receivedCrc !=
+                        calculateCrc8(scratchpad.data(), scratchpad.size()))) {
+          result = make_error_code(CrcError);
+        }
+      }
+    }
+  }
+  return result;
+}
+
+error_code DS1920::copyScratchpad() {
+  error_code result = selectRom(*master);
+  if (!result) {
+    result =
+        master->writeByteSetLevel(COPY_SCRATCHPAD, OneWireMaster::StrongLevel);
+    if (!result) {
+      (*sleep)(10);
+      result = master->setLevel(OneWireMaster::NormalLevel);
+    }
+  }
+  return result;
+}
+
+error_code DS1920::convertTemperature() {
+  error_code result = selectRom(*master);
+  if (!result) {
+    result =
+        master->writeByteSetLevel(CONV_TEMPERATURE, OneWireMaster::StrongLevel);
+    if (!result) {
+      (*sleep)(750);
+      result = master->setLevel(OneWireMaster::NormalLevel);
+    }
+  }
+  return result;
+}
+
+error_code DS1920::recallEeprom() {
+  error_code result = selectRom(*master);
+  if (!result) {
+    result = master->writeByte(RECALL);
+  }
+  return result;
+}
+
+const error_category & DS1920::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "DS1920"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case CrcError:
+        return "CRC Error";
+
+      case DataError:
+        return "Data Error";
+
+      default:
+        return defaultErrorMessage(condition);
+      }
+    }
+  } instance;
+  return instance;
+}
+
+error_code readTemperature(DS1920 & ds1920, int & temperature) {
+  error_code result = ds1920.convertTemperature();
+  if (result) {
+    return result;
+  }
+  DS1920::Scratchpad scratchpad;
+  result = ds1920.readScratchpad(scratchpad);
+  if (result) {
+    return result;
+  }
+
+  unsigned int tempData =
+      (static_cast<unsigned int>(scratchpad[1]) << 8) | scratchpad[0];
+  const unsigned int signMask = 0xFF00;
+  if ((tempData & signMask) == signMask) {
+    temperature = -0x100;
+    tempData &= ~signMask;
+  } else if ((tempData & signMask) == 0) {
+    temperature = 0;
+  } else {
+    return make_error_code(DS1920::DataError);
+  }
+  temperature += static_cast<int>(tempData);
+  return error_code();
+}
+
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS1920.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,118 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_DS1920
+#define MaximInterface_DS1920
+
+#include <MaximInterface/Links/SelectRom.hpp>
+#include <MaximInterface/Links/Sleep.hpp>
+#include <MaximInterface/Utilities/Export.h>
+
+namespace MaximInterface {
+
+/// DS1920 1-Wire Temperature iButton
+/// @details The iButton® temperature logger (DS1920) provides
+/// direct-to-digital 9-bit temperature readings over a range of
+/// -55°C to +100°C in 0.5° increments. The iButton communicates with
+/// a processor using the 1-Wire® protocol through a hardware port
+/// interface. The port interface provides both the physical link and
+/// handles the communication protocols that enable the processor to
+/// access iButton resources with simple commands. Two bytes of
+/// EEPROM can be used either to set alarm triggers or for storing
+/// user data.
+class DS1920 {
+public:
+  enum ErrorValue { CrcError = 1, DataError };
+
+  /// Holds the contents of the device scratchpad.
+  typedef array<uint_least8_t, 8> Scratchpad;
+
+  DS1920(const Sleep & sleep, OneWireMaster & master,
+         const SelectRom & selectRom)
+      : selectRom(selectRom), master(&master), sleep(&sleep) {}
+
+  void setSleep(const Sleep & sleep) { this->sleep = &sleep; }
+  void setMaster(OneWireMaster & master) { this->master = &master; }
+  void setSelectRom(const SelectRom & selectRom) {
+    this->selectRom = selectRom;
+  }
+
+  /// Write Scratchpad Command
+  /// @details If the result of a temperature measurement is higher
+  /// than TH or lower than TL, an alarm flag inside the device is
+  /// set. This flag is updated with every temperature measurement.
+  /// As long as the alarm flag is set, the DS1920 will respond to
+  /// the alarm search command.
+  /// @param[in] th 8-bit upper temperature threshold, MSB indicates sign.
+  /// @param[in] tl 8-bit lower temperature threshold, MSB indicates sign.
+  MaximInterface_EXPORT error_code writeScratchpad(uint_least8_t th,
+                                                   uint_least8_t tl);
+
+  /// Read Scratchpad Command
+  /// @param[out] scratchpad Contents of scratchpad.
+  MaximInterface_EXPORT error_code readScratchpad(Scratchpad & scratchpad);
+
+  /// Copy Scratchpad Command
+  /// @details This command copies from the scratchpad into the
+  /// EEPROM of the DS1920, storing the temperature trigger bytes
+  /// in nonvolatile memory.
+  MaximInterface_EXPORT error_code copyScratchpad();
+
+  /// Convert Temperature Command
+  /// @details This command begins a temperature conversion.
+  MaximInterface_EXPORT error_code convertTemperature();
+
+  /// Recall Command
+  /// @details This command recalls the temperature trigger values
+  /// stored in EEPROM to the scratchpad.
+  MaximInterface_EXPORT error_code recallEeprom();
+
+  MaximInterface_EXPORT static const error_category & errorCategory();
+
+private:
+  SelectRom selectRom;
+  OneWireMaster * master;
+  const Sleep * sleep;
+};
+
+/// Reads the current temperature as an integer value.
+/// @param[out] temperature Temperature in degrees Celsius multiplied by 16.
+MaximInterface_EXPORT error_code readTemperature(DS1920 & ds1920,
+                                                 int & temperature);
+
+inline error_code make_error_code(DS1920::ErrorValue e) {
+  return error_code(e, DS1920::errorCategory());
+}
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS2413.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,127 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <MaximInterface/Links/OneWireMaster.hpp>
+#include <MaximInterface/Utilities/Error.hpp>
+#include "DS2413.hpp"
+
+namespace MaximInterface {
+
+error_code DS2413::readStatus(Status & status) const {
+  uint_least8_t val;
+  const error_code result = pioAccessRead(val);
+  if (!result) {
+    status.pioAInputState = (val & 0x1) == 0x1;
+    status.pioAOutputState = (val & 0x2) == 0x2;
+    status.pioBInputState = (val & 0x4) == 0x4;
+    status.pioBOutputState = (val & 0x8) == 0x8;
+  }
+  return result;
+}
+
+error_code DS2413::writeOutputState(bool pioAState, bool pioBState) {
+  uint_least8_t val = 0xFC;
+  if (pioAState) {
+    val |= 0x1;
+  }
+  if (pioBState) {
+    val |= 0x2;
+  }
+  return pioAccessWrite(val);
+}
+
+error_code DS2413::pioAccessRead(uint_least8_t & val) const {
+  error_code result = selectRom(*master);
+  if (!result) {
+    result = master->writeByte(0xF5);
+    if (!result) {
+      result = master->readByte(val);
+      if (!result && (val != ((val ^ 0xF0) >> 4))) {
+        result = make_error_code(CommunicationError);
+      }
+    }
+  }
+  return result;
+}
+
+error_code DS2413::pioAccessWrite(uint_least8_t val) {
+  error_code result = selectRom(*master);
+  if (!result) {
+    uint_least8_t block[] = {0x5A, val, static_cast<uint_least8_t>(val ^ 0xFF)};
+    result = master->writeBlock(block, sizeof(block) / sizeof(block[0]));
+    if (!result) {
+      result = master->readByte(block[0]);
+      if (!result && block[0] != 0xAA) {
+        result = make_error_code(CommunicationError);
+      }
+    }
+  }
+  return result;
+}
+
+const error_category & DS2413::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "DS2413"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case CommunicationError:
+        return "Communication Error";
+
+      default:
+        return defaultErrorMessage(condition);
+      }
+    }
+  } instance;
+  return instance;
+}
+
+error_code writePioAOutputState(DS2413 & ds2413, bool pioAState) {
+  DS2413::Status status;
+  error_code result = ds2413.readStatus(status);
+  if (!result && pioAState != status.pioAOutputState) {
+    result = ds2413.writeOutputState(pioAState, status.pioBOutputState);
+  }
+  return result;
+}
+
+error_code writePioBOutputState(DS2413 & ds2413, bool pioBState) {
+  DS2413::Status status;
+  error_code result = ds2413.readStatus(status);
+  if (!result && pioBState != status.pioBOutputState) {
+    result = ds2413.writeOutputState(status.pioAOutputState, pioBState);
+  }
+  return result;
+}
+
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS2413.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,102 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_DS2413
+#define MaximInterface_DS2413
+
+#include <stdint.h>
+#include <MaximInterface/Links/SelectRom.hpp>
+#include <MaximInterface/Utilities/Export.h>
+
+namespace MaximInterface {
+
+/// DS2413 1-Wire Dual Channel Addressable Switch
+/// @details The DS2413 is a dual-channel programmable I/O 1-Wire®
+/// chip. The PIO outputs are configured as open-drain and provide up
+/// to 20mA continuous sink capability and off-state operating voltage
+/// up to 28V. Control and sensing of the PIO pins is performed with
+/// a dedicated device-level command protocol. To provide a high level
+/// of fault tolerance in the end application, the 1-Wire I/O and PIO
+/// pins are all capable of withstanding continuous application of
+/// voltages up to 28V max. Communication and operation of the DS2413
+/// is performed with the single contact Maxim 1-Wire serial interface.
+class DS2413 {
+public:
+  enum ErrorValue { CommunicationError = 1 };
+
+  struct Status {
+    bool pioAInputState;
+    bool pioAOutputState;
+    bool pioBInputState;
+    bool pioBOutputState;
+  };
+
+  DS2413(OneWireMaster & master, const SelectRom & selectRom)
+      : selectRom(selectRom), master(&master) {}
+
+  void setMaster(OneWireMaster & master) { this->master = &master; }
+  void setSelectRom(const SelectRom & selectRom) {
+    this->selectRom = selectRom;
+  }
+
+  /// Read the input and output logic states for all PIO pins.
+  MaximInterface_EXPORT error_code readStatus(Status & status) const;
+
+  /// Write the output logic states for all PIO pins.
+  MaximInterface_EXPORT error_code writeOutputState(bool pioAState,
+                                                    bool pioBState);
+
+  MaximInterface_EXPORT static const error_category & errorCategory();
+
+private:
+  error_code pioAccessRead(uint_least8_t & val) const;
+  error_code pioAccessWrite(uint_least8_t val);
+
+  SelectRom selectRom;
+  OneWireMaster * master;
+};
+
+/// @{
+/// Write the output logic state for only a single PIO pin.
+MaximInterface_EXPORT error_code writePioAOutputState(DS2413 & ds2413,
+                                                      bool pioAState);
+MaximInterface_EXPORT error_code writePioBOutputState(DS2413 & ds2413,
+                                                      bool pioBState);
+/// @}
+
+inline error_code make_error_code(DS2413::ErrorValue e) {
+  return error_code(e, DS2413::errorCategory());
+}
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS2431.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,187 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <algorithm>
+#include <MaximInterface/Links/OneWireMaster.hpp>
+#include <MaximInterface/Utilities/Error.hpp>
+#include "DS2431.hpp"
+
+namespace MaximInterface {
+
+enum Command {
+  WriteScratchpad = 0x0F,
+  ReadScratchpad = 0xAA,
+  CopyScratchpad = 0x55,
+  ReadMemory = 0xF0
+};
+
+error_code writeMemory(DS2431 & device, DS2431::Address targetAddress,
+                       const DS2431::Scratchpad & data) {
+  error_code result = device.writeScratchpad(targetAddress, data);
+  if (result) {
+    return result;
+  }
+  DS2431::Scratchpad readData;
+  uint_least8_t esByte;
+  result = device.readScratchpad(readData, esByte);
+  if (result) {
+    return result;
+  }
+  result = device.copyScratchpad(targetAddress, esByte);
+  return result;
+}
+
+error_code DS2431::readMemory(Address beginAddress, uint_least8_t * data,
+                              size_t dataLen) const {
+  error_code owmResult = selectRom(*master);
+  if (owmResult) {
+    return owmResult;
+  }
+  const uint_least8_t sendBlock[] = {ReadMemory, beginAddress, 0x00};
+  owmResult =
+      master->writeBlock(sendBlock, sizeof(sendBlock) / sizeof(sendBlock[0]));
+  if (owmResult) {
+    return owmResult;
+  }
+  owmResult = master->readBlock(data, dataLen);
+  return owmResult;
+}
+
+error_code DS2431::writeScratchpad(Address targetAddress,
+                                   const Scratchpad & data) {
+  error_code owmResult = selectRom(*master);
+  if (owmResult) {
+    return owmResult;
+  }
+  array<uint_least8_t, 3 + Scratchpad::csize> block = {WriteScratchpad,
+                                                       targetAddress, 0x00};
+  std::copy(data.begin(), data.end(), block.begin() + 3);
+  owmResult = master->writeBlock(block.data(), block.size());
+  if (owmResult) {
+    return owmResult;
+  }
+  const uint_fast16_t calculatedCrc =
+      calculateCrc16(block.data(), block.size()) ^ 0xFFFFU;
+  owmResult = master->readBlock(block.data(), 2);
+  if (owmResult) {
+    return owmResult;
+  }
+  if (calculatedCrc !=
+      ((static_cast<uint_fast16_t>(block[1]) << 8) | block[0])) {
+    owmResult = make_error_code(CrcError);
+  }
+  return owmResult;
+}
+
+error_code DS2431::readScratchpad(Scratchpad & data, uint_least8_t & esByte) {
+  typedef array<uint_least8_t, 6 + Scratchpad::csize> Block;
+
+  error_code owmResult = selectRom(*master);
+  if (owmResult) {
+    return owmResult;
+  }
+  Block block = {ReadScratchpad};
+  owmResult = master->writeByte(block.front());
+  if (owmResult) {
+    return owmResult;
+  }
+  owmResult = master->readBlock(block.data() + 1, block.size() - 1);
+  if (owmResult) {
+    return owmResult;
+  }
+  Block::const_iterator blockIt = block.end();
+  uint_fast16_t receivedCrc = static_cast<uint_fast16_t>(*(--blockIt)) << 8;
+  receivedCrc |= *(--blockIt);
+  const uint_fast16_t expectedCrc =
+      calculateCrc16(block.data(), block.size() - 2) ^ 0xFFFFU;
+  if (expectedCrc == receivedCrc) {
+    Block::const_iterator blockItEnd = blockIt;
+    blockIt -= data.size();
+    std::copy(blockIt, blockItEnd, data.begin());
+    esByte = *(--blockIt);
+  } else {
+    owmResult = make_error_code(CrcError);
+  }
+  return owmResult;
+}
+
+error_code DS2431::copyScratchpad(Address targetAddress, uint_least8_t esByte) {
+  error_code owmResult = selectRom(*master);
+  if (owmResult) {
+    return owmResult;
+  }
+  uint_least8_t block[] = {CopyScratchpad, targetAddress, 0x00};
+  owmResult = master->writeBlock(block, sizeof(block) / sizeof(block[0]));
+  if (owmResult) {
+    return owmResult;
+  }
+  owmResult = master->writeByteSetLevel(esByte, OneWireMaster::StrongLevel);
+  if (owmResult) {
+    return owmResult;
+  }
+  (*sleep)(10);
+  owmResult = master->setLevel(OneWireMaster::NormalLevel);
+  if (owmResult) {
+    return owmResult;
+  }
+  owmResult = master->readByte(block[0]);
+  if (owmResult) {
+    return owmResult;
+  }
+  if (block[0] != 0xAA) {
+    owmResult = make_error_code(OperationFailure);
+  }
+  return owmResult;
+}
+
+const error_category & DS2431::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "DS2431"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case CrcError:
+        return "CRC Error";
+
+      case OperationFailure:
+        return "Operation Failure";
+
+      default:
+        return defaultErrorMessage(condition);
+      }
+    }
+  } instance;
+  return instance;
+}
+
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS2431.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,121 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_DS2431
+#define MaximInterface_DS2431
+
+#include <MaximInterface/Links/SelectRom.hpp>
+#include <MaximInterface/Links/Sleep.hpp>
+#include <MaximInterface/Utilities/Export.h>
+
+namespace MaximInterface {
+
+/// DS2431 1024-bit 1-Wire EEPROM
+/// @details The DS2431 is a 1024-bit, 1-Wire® EEPROM chip organized
+/// as four memory pages of 256 bits each. Data is written to an 8-byte
+/// scratchpad, verified, and then copied to the EEPROM memory. As a
+/// special feature, the four memory pages can individually be write
+/// protected or put in EPROM-emulation mode, where bits can only be
+/// changed from a 1 to a 0 state. The DS2431 communicates over the
+/// single-conductor 1-Wire bus. The communication follows the standard
+/// 1-Wire protocol. Each device has its own unalterable and unique
+/// 64-bit ROM registration number that is factory lasered into the chip.
+/// The registration number is used to address the device in a multidrop,
+/// 1-Wire net environment.
+class DS2431 {
+public:
+  enum ErrorValue { CrcError = 1, OperationFailure };
+
+  typedef array<uint_least8_t, 8> Scratchpad;
+  typedef uint_least8_t Address;
+
+  DS2431(const Sleep & sleep, OneWireMaster & master,
+         const SelectRom & selectRom)
+      : selectRom(selectRom), master(&master), sleep(&sleep) {}
+
+  void setSleep(const Sleep & sleep) { this->sleep = &sleep; }
+  void setMaster(OneWireMaster & master) { this->master = &master; }
+  void setSelectRom(const SelectRom & selectRom) {
+    this->selectRom = selectRom;
+  }
+
+  /// Reads block of data from EEPROM memory.
+  /// @param[in] beginAddress EEPROM memory address to start reading from.
+  /// @param[out] data EEPROM data read from the device.
+  /// @param[in] dataLen Length of data parameter and number of bytes to read.
+  MaximInterface_EXPORT error_code readMemory(Address beginAddress,
+                                              uint_least8_t * data,
+                                              size_t dataLen) const;
+
+  /// Writes 8 bytes to the scratchpad.
+  /// @param[in] targetAddress EEPROM memory address that this data.
+  /// will be copied to.  Must be on row boundary.
+  /// @param[in] data Data to write to scratchpad.
+  MaximInterface_EXPORT error_code writeScratchpad(Address targetAddress,
+                                                   const Scratchpad & data);
+
+  /// Reads contents of scratchpad.
+  /// @param[out] data Data read from scratchpad.
+  /// @param[out] esByte E/S byte read before scratchpad data.
+  MaximInterface_EXPORT error_code readScratchpad(Scratchpad & data,
+                                                  uint_least8_t & esByte);
+
+  /// Copies contents of scratchpad to EEPROM.
+  /// @param[in] targetAddress EEPROM memory address that scratchpad
+  /// will be copied to. Must be on row boundary.
+  /// @param[in] esByte E/S byte from preceding Read Scratchpad command.
+  MaximInterface_EXPORT error_code copyScratchpad(Address targetAddress,
+                                                  uint_least8_t esByte);
+
+  MaximInterface_EXPORT static const error_category & errorCategory();
+
+private:
+  SelectRom selectRom;
+  OneWireMaster * master;
+  const Sleep * sleep;
+};
+
+/// Writes data to EEPROM using Write Scratchpad, Read Scratchpad,
+/// and Copy Scratchpad commands.
+/// @param[in] targetAddress EEPROM memory address to start writing at.
+/// @param[in] data Data to write to EEPROM.
+MaximInterface_EXPORT error_code writeMemory(DS2431 & device,
+                                             DS2431::Address targetAddress,
+                                             const DS2431::Scratchpad & data);
+
+inline error_code make_error_code(DS2431::ErrorValue e) {
+  return error_code(e, DS2431::errorCategory());
+}
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS2465.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,827 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <MaximInterface/Utilities/Error.hpp>
+#include "DS2465.hpp"
+
+namespace MaximInterface {
+
+using namespace Sha256;
+
+enum MemoryAddress {
+  Scratchpad = 0x00,
+  CommandReg = 0x60,
+  StatusReg = 0x61,
+  ReadDataReg = 0x62,
+  MacReadoutReg = 0x63,
+  MemoryProtectionReg = 0x64,
+  ConfigReg = 0x67,
+  tRSTL_Reg = 0x68,
+  tMSP_Reg = 0x69,
+  tW0L_Reg = 0x6A,
+  tREC0_Reg = 0x6B,
+  RWPU_Reg = 0x6C,
+  tW1L_Reg = 0x6D,
+  UserMemoryPage0 = 0x80,
+  UserMemoryPage1 = 0xA0
+};
+
+/// Delay required after writing an EEPROM segment.
+static const int eepromSegmentWriteDelayMs = 10;
+/// Delay required after writing an EEPROM page such as the secret memory.
+static const int eepromPageWriteDelayMs = 8 * eepromSegmentWriteDelayMs;
+/// Delay required for a SHA computation to complete.
+static const int shaComputationDelayMs = 2;
+
+/// DS2465 Commands
+enum Command {
+  DeviceResetCmd = 0xF0,
+  WriteDeviceConfigCmd = 0xD2,
+  OwResetCmd = 0xB4,
+  OwWriteByteCmd = 0xA5,
+  OwReadByteCmd = 0x96,
+  OwSingleBitCmd = 0x87,
+  OwTripletCmd = 0x78,
+  OwTransmitBlockCmd = 0x69,
+  OwReceiveBlockCmd = 0xE1,
+  CopyScratchpadCmd = 0x5A,
+  ComputeSlaveSecretCmd = 0x4B,
+  ComputeSlaveAuthMacCmd = 0x3C,
+  ComputeSlaveWriteMacCmd = 0x2D,
+  ComputeNextMasterSecretCmd = 0x1E,
+  SetProtectionCmd = 0x0F
+};
+
+/// DS2465 Status Bits
+enum StatusBit {
+  Status_1WB = 0x01,
+  Status_PPD = 0x02,
+  Status_SD = 0x04,
+  Status_LL = 0x08,
+  Status_RST = 0x10,
+  Status_SBR = 0x20,
+  Status_TSB = 0x40,
+  Status_DIR = 0x80
+};
+
+static const size_t maxBlockSize = 63;
+
+error_code DS2465::initialize(Config config) {
+  // reset DS2465
+  error_code result = resetDevice();
+  if (!result) {
+    // write the default configuration setup
+    result = writeConfig(config);
+  }
+  return result;
+}
+
+error_code DS2465::computeNextMasterSecret(bool swap, int pageNum,
+                                           PageRegion region) {
+  error_code result = make_error_code(ArgumentOutOfRangeError);
+  if (pageNum >= 0) {
+    uint_least8_t command[] = {
+        ComputeNextMasterSecretCmd,
+        static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
+                                        : 0xBF)};
+    result =
+        writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
+  }
+  return result;
+}
+
+error_code DS2465::computeWriteMac(bool regwrite, bool swap, int pageNum,
+                                   int segmentNum) const {
+  error_code result = make_error_code(ArgumentOutOfRangeError);
+  if (pageNum >= 0 && segmentNum >= 0) {
+    uint_least8_t command[] = {
+        ComputeSlaveWriteMacCmd,
+        static_cast<uint_least8_t>((regwrite << 7) | (swap << 6) |
+                                   (pageNum << 4) | segmentNum)};
+    result =
+        writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
+    if (!result) {
+      (*sleep)(shaComputationDelayMs);
+    }
+  }
+  return result;
+}
+
+error_code DS2465::computeAuthMac(bool swap, int pageNum,
+                                  PageRegion region) const {
+  error_code result = make_error_code(ArgumentOutOfRangeError);
+  if (pageNum >= 0) {
+    uint_least8_t command[] = {
+        ComputeSlaveAuthMacCmd,
+        static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
+                                        : 0xBF)};
+    result =
+        writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
+    if (!result) {
+      (*sleep)(shaComputationDelayMs * 2);
+    }
+  }
+  return result;
+}
+
+error_code DS2465::computeSlaveSecret(bool swap, int pageNum,
+                                      PageRegion region) {
+  error_code result = make_error_code(ArgumentOutOfRangeError);
+  if (pageNum >= 0) {
+    uint_least8_t command[] = {
+        ComputeSlaveSecretCmd,
+        static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
+                                        : 0xBF)};
+    result =
+        writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
+    if (!result) {
+      (*sleep)(shaComputationDelayMs * 2);
+    }
+  }
+  return result;
+}
+
+error_code DS2465::readPage(int pageNum, Page & data) const {
+  uint_least8_t addr;
+  switch (pageNum) {
+  case 0:
+    addr = UserMemoryPage0;
+    break;
+  case 1:
+    addr = UserMemoryPage1;
+    break;
+  default:
+    return make_error_code(ArgumentOutOfRangeError);
+  }
+  return readMemory(addr, data.data(), data.size());
+}
+
+error_code DS2465::writePage(int pageNum, const Page & data) {
+  error_code result = writeMemory(Scratchpad, data.data(), data.size());
+  if (!result) {
+    result = copyScratchpad(false, pageNum, false, 0);
+  }
+  if (!result) {
+    (*sleep)(eepromPageWriteDelayMs);
+  }
+  return result;
+}
+
+error_code DS2465::writeSegment(int pageNum, int segmentNum,
+                                const Segment & data) {
+  error_code result = writeMemory(Scratchpad, data.data(), data.size());
+  if (!result) {
+    result = copyScratchpad(false, pageNum, true, segmentNum);
+  }
+  if (!result) {
+    (*sleep)(eepromSegmentWriteDelayMs);
+  }
+  return result;
+}
+
+error_code DS2465::writeMasterSecret(const Hash & masterSecret) {
+  error_code result =
+      writeMemory(Scratchpad, masterSecret.data(), masterSecret.size());
+  if (!result) {
+    result = copyScratchpad(true, 0, false, 0);
+  }
+  if (!result) {
+    (*sleep)(eepromPageWriteDelayMs);
+  }
+  return result;
+}
+
+error_code DS2465::copyScratchpad(bool destSecret, int pageNum, bool notFull,
+                                  int segmentNum) {
+  error_code result = make_error_code(ArgumentOutOfRangeError);
+  if (pageNum >= 0 && segmentNum >= 0) {
+    uint_least8_t command[] = {
+        CopyScratchpadCmd,
+        static_cast<uint_least8_t>(destSecret ? 0
+                                              : (0x80 | (pageNum << 4) |
+                                                 (notFull << 3) | segmentNum))};
+    result =
+        writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
+  }
+  return result;
+}
+
+error_code DS2465::configureLevel(Level level) {
+  // Check if supported level
+  if (!((level == NormalLevel) || (level == StrongLevel))) {
+    return make_error_code(InvalidLevelError);
+  }
+  // Check if requested level already set
+  if (curConfig.getSPU() == (level == StrongLevel)) {
+    return error_code();
+  }
+  // Set the level
+  Config newConfig = curConfig;
+  newConfig.setSPU(level == StrongLevel);
+  return writeConfig(newConfig);
+}
+
+error_code DS2465::setLevel(Level newLevel) {
+  if (newLevel == StrongLevel) {
+    return make_error_code(InvalidLevelError);
+  }
+
+  return configureLevel(newLevel);
+}
+
+error_code DS2465::setSpeed(Speed newSpeed) {
+  // Check if supported speed
+  if (!((newSpeed == OverdriveSpeed) || (newSpeed == StandardSpeed))) {
+    return make_error_code(InvalidSpeedError);
+  }
+  // Check if requested speed is already set
+  if (curConfig.get1WS() == (newSpeed == OverdriveSpeed)) {
+    return error_code();
+  }
+  // Set the speed
+  Config newConfig = curConfig;
+  newConfig.set1WS(newSpeed == OverdriveSpeed);
+  return writeConfig(newConfig);
+}
+
+error_code DS2465::triplet(TripletData & data) {
+  // 1-Wire Triplet (Case B)
+  //   S AD,0 [A] 1WT [A] SS [A] Sr AD,1 [A] [Status] A [Status] A\ P
+  //                                         \--------/
+  //                           Repeat until 1WB bit has changed to 0
+  //  [] indicates from slave
+  //  SS indicates byte containing search direction bit value in msbit
+
+  const uint_least8_t command[] = {
+      OwTripletCmd, static_cast<uint_least8_t>(data.writeBit ? 0x80 : 0x00)};
+  error_code result =
+      writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
+  if (!result) {
+    uint_least8_t status;
+    result = pollBusy(&status);
+    if (!result) {
+      // check bit results in status byte
+      data.readBit = ((status & Status_SBR) == Status_SBR);
+      data.readBitComplement = ((status & Status_TSB) == Status_TSB);
+      data.writeBit = ((status & Status_DIR) == Status_DIR);
+    }
+  }
+  return result;
+}
+
+error_code DS2465::readBlock(uint_least8_t * recvBuf, size_t recvLen) {
+  // 1-Wire Receive Block (Case A)
+  //   S AD,0 [A] CommandReg [A] 1WRF [A] PR [A] P
+  //  [] indicates from slave
+  //  PR indicates byte containing parameter
+
+  error_code result;
+  while ((recvLen > 0) && !result) {
+    const uint_least8_t command[] = {
+        OwReceiveBlockCmd,
+        static_cast<uint_least8_t>(std::min(recvLen, maxBlockSize))};
+    result =
+        writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
+    if (!result) {
+      result = pollBusy();
+    }
+    if (!result) {
+      result = readMemory(Scratchpad, recvBuf, command[1]);
+    }
+    recvBuf += command[1];
+    recvLen -= command[1];
+  }
+  return result;
+}
+
+error_code DS2465::writeBlock(const uint_least8_t * sendBuf, size_t sendLen) {
+  error_code result;
+  while ((sendLen > 0) && !result) {
+    const uint_least8_t command[] = {
+        OwTransmitBlockCmd,
+        static_cast<uint_least8_t>(std::min(sendLen, maxBlockSize))};
+
+    // prefill scratchpad with required data
+    result = writeMemory(Scratchpad, sendBuf, command[1]);
+
+    // 1-Wire Transmit Block (Case A)
+    //   S AD,0 [A] CommandReg [A] 1WTB [A] PR [A] P
+    //  [] indicates from slave
+    //  PR indicates byte containing parameter
+    if (!result) {
+      result = writeMemory(CommandReg, command,
+                           sizeof(command) / sizeof(command[0]));
+    }
+    if (!result) {
+      result = pollBusy();
+    }
+    sendBuf += command[1];
+    sendLen -= command[1];
+  }
+  return result;
+}
+
+error_code DS2465::writeMacBlock() const {
+  // 1-Wire Transmit Block (Case A)
+  //   S AD,0 [A] CommandReg [A] 1WTB [A] PR [A] P
+  //  [] indicates from slave
+  //  PR indicates byte containing parameter
+
+  const uint_least8_t command[] = {OwTransmitBlockCmd, 0xFF};
+  error_code result =
+      writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
+  if (!result) {
+    result = pollBusy();
+  }
+  return result;
+}
+
+error_code DS2465::readByteSetLevel(uint_least8_t & recvByte,
+                                    Level afterLevel) {
+  // 1-Wire Read Bytes (Case C)
+  //   S AD,0 [A] CommandReg [A] 1WRB [A] Sr AD,1 [A] [Status] A [Status] A
+  //                                                  \--------/
+  //                     Repeat until 1WB bit has changed to 0
+  //   Sr AD,0 [A] SRP [A] E1 [A] Sr AD,1 [A] DD A\ P
+  //
+  //  [] indicates from slave
+  //  DD data read
+
+  error_code result = configureLevel(afterLevel);
+  if (result) {
+    return result;
+  }
+
+  uint_least8_t buf = OwReadByteCmd;
+  result = writeMemory(CommandReg, &buf, 1);
+
+  if (!result) {
+    result = pollBusy();
+  }
+
+  if (!result) {
+    result = readMemory(ReadDataReg, &buf, 1);
+  }
+
+  if (!result) {
+    recvByte = buf;
+  }
+
+  return result;
+}
+
+error_code DS2465::writeByteSetLevel(uint_least8_t sendByte, Level afterLevel) {
+  // 1-Wire Write Byte (Case B)
+  //   S AD,0 [A] CommandReg [A] 1WWB [A] DD [A] Sr AD,1 [A] [Status] A [Status]
+  //   A\ P
+  //                                                           \--------/
+  //                             Repeat until 1WB bit has changed to 0
+  //  [] indicates from slave
+  //  DD data to write
+
+  error_code result = configureLevel(afterLevel);
+  if (result) {
+    return result;
+  }
+
+  const uint_least8_t command[] = {OwWriteByteCmd, sendByte};
+
+  result =
+      writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
+  if (!result) {
+    result = pollBusy();
+  }
+
+  return result;
+}
+
+error_code DS2465::touchBitSetLevel(bool & sendRecvBit, Level afterLevel) {
+  // 1-Wire bit (Case B)
+  //   S AD,0 [A] CommandReg [A] 1WSB [A] BB [A] Sr AD,1 [A] [Status] A [Status]
+  //   A\ P
+  //                                                          \--------/
+  //                           Repeat until 1WB bit has changed to 0
+  //  [] indicates from slave
+  //  BB indicates byte containing bit value in msbit
+
+  error_code result = configureLevel(afterLevel);
+  if (result) {
+    return result;
+  }
+
+  const uint_least8_t command[] = {
+      OwSingleBitCmd, static_cast<uint_least8_t>(sendRecvBit ? 0x80 : 0x00)};
+  uint_least8_t status;
+
+  result =
+      writeMemory(CommandReg, command, sizeof(command) / sizeof(command[0]));
+
+  if (!result) {
+    result = pollBusy(&status);
+  }
+
+  if (!result) {
+    sendRecvBit = ((status & Status_SBR) == Status_SBR);
+  }
+
+  return result;
+}
+
+error_code DS2465::writeMemory(uint_least8_t addr, const uint_least8_t * buf,
+                               size_t bufLen) const {
+  // Write SRAM (Case A)
+  //   S AD,0 [A] VSA [A] DD [A]  P
+  //                      \-----/
+  //                        Repeat for each data byte
+  //  [] indicates from slave
+  //  VSA valid SRAM memory address
+  //  DD memory data to write
+
+  error_code result = i2cMaster->start(i2cAddress_);
+  if (result) {
+    i2cMaster->stop();
+    return result;
+  }
+  result = i2cMaster->writeByte(addr);
+  if (result) {
+    i2cMaster->stop();
+    return result;
+  }
+  result = i2cMaster->writeBlock(buf, bufLen);
+  if (result) {
+    i2cMaster->stop();
+    return result;
+  }
+  result = i2cMaster->stop();
+  return result;
+}
+
+error_code DS2465::readMemory(uint_least8_t addr, uint_least8_t * buf,
+                              size_t bufLen) const {
+  // Read (Case A)
+  //   S AD,0 [A] MA [A] Sr AD,1 [A] [DD] A [DD] A\ P
+  //                                 \-----/
+  //                                   Repeat for each data byte, NAK last byte
+  //  [] indicates from slave
+  //  MA memory address
+  //  DD memory data read
+
+  error_code result = i2cMaster->start(i2cAddress_);
+  if (result) {
+    i2cMaster->stop();
+    return result;
+  }
+  result = i2cMaster->writeByte(addr);
+  if (result) {
+    i2cMaster->stop();
+    return result;
+  }
+  result = readMemory(buf, bufLen);
+  return result;
+}
+
+error_code DS2465::readMemory(uint_least8_t * buf, size_t bufLen) const {
+  error_code result = i2cMaster->start(i2cAddress_ | 1);
+  if (result) {
+    i2cMaster->stop();
+    return result;
+  }
+  result = i2cMaster->readBlock(I2CMaster::Nack, buf, bufLen);
+  if (result) {
+    i2cMaster->stop();
+    return result;
+  }
+  result = i2cMaster->stop();
+  return result;
+}
+
+error_code DS2465::writeConfig(Config config) {
+  uint_least8_t configBuf = ((config.readByte() ^ 0xF) << 4) | config.readByte();
+  error_code result = writeMemory(ConfigReg, &configBuf, 1);
+  if (!result) {
+    result = readMemory(ConfigReg, &configBuf, 1);
+  }
+  if (!result) {
+    if (configBuf != config.readByte())
+      result = make_error_code(HardwareError);
+  }
+  if (!result) {
+    curConfig = config;
+  }
+  return result;
+}
+
+error_code DS2465::writePortParameter(PortParameter param, int val) {
+  if (val < 0 || val > 15) {
+    return make_error_code(ArgumentOutOfRangeError);
+  }
+
+  uint_least8_t addr = 0;
+  switch (param) {
+  case tRSTL_STD:
+  case tRSTL_OD:
+    addr = tRSTL_Reg;
+    break;
+  case tMSP_STD:
+  case tMSP_OD:
+    addr = tMSP_Reg;
+    break;
+  case tW0L_STD:
+  case tW0L_OD:
+    addr = tW0L_Reg;
+    break;
+  case tREC0:
+    addr = tREC0_Reg;
+    break;
+  case RWPU:
+    addr = RWPU_Reg;
+    break;
+  case tW1L_OD:
+    addr = tW1L_Reg;
+    break;
+  }
+
+  uint_least8_t data;
+  error_code result = readMemory(addr, &data, 1);
+  if (result) {
+    return result;
+  }
+
+  uint_least8_t newData;
+  if (param == tRSTL_OD || param == tMSP_OD || param == tW0L_OD) {
+    newData = (data & 0x0F) | (val << 4);
+  } else {
+    newData = (data & 0xF0) | val;
+  }
+
+  if (newData != data) {
+    result = writeMemory(addr, &newData, 1);
+  }
+  return result;
+}
+
+error_code DS2465::pollBusy(uint_least8_t * pStatus) const {
+  const int pollLimit = 200;
+
+  int pollCount = 0;
+  uint_least8_t status;
+  do {
+    error_code result = readMemory(&status, 1);
+    if (result) {
+      return result;
+    }
+    if (pStatus != NULL) {
+      *pStatus = status;
+    }
+    if (pollCount++ >= pollLimit) {
+      return make_error_code(HardwareError);
+    }
+  } while (status & Status_1WB);
+
+  return error_code();
+}
+
+error_code DS2465::reset() {
+  // 1-Wire reset (Case B)
+  //   S AD,0 [A] CommandReg  [A] 1WRS [A] Sr AD,1 [A] [Status] A [Status] A\ P
+  //                                                  \--------/
+  //                       Repeat until 1WB bit has changed to 0
+  //  [] indicates from slave
+
+  uint_least8_t buf = OwResetCmd;
+  error_code result = writeMemory(CommandReg, &buf, 1);
+
+  if (!result) {
+    result = pollBusy(&buf);
+  }
+
+  if (!result) {
+    if ((buf & Status_SD) == Status_SD) {
+      result = make_error_code(ShortDetectedError);
+    }
+    else if ((buf & Status_PPD) != Status_PPD) {
+      result = make_error_code(NoSlaveError);
+    }
+  }
+
+  return result;
+}
+
+error_code DS2465::resetDevice() {
+  // Device Reset
+  //   S AD,0 [A] CommandReg [A] 1WMR [A] Sr AD,1 [A] [SS] A\ P
+  //  [] indicates from slave
+  //  SS status byte to read to verify state
+
+  uint_least8_t buf = DeviceResetCmd;
+  error_code result = writeMemory(CommandReg, &buf, 1);
+
+  if (!result) {
+    result = readMemory(&buf, 1);
+  }
+
+  if (!result) {
+    if ((buf & 0xF7) != 0x10) {
+      result = make_error_code(HardwareError);
+    }
+  }
+
+  if (!result) {
+    reset(); // do a command to get 1-Wire master reset out of holding state
+  }
+
+  return result;
+}
+
+error_code DS2465::computeNextMasterSecret(const SlaveSecretData & data) {
+  error_code result = writeMemory(Scratchpad, data.data(), data.size());
+  if (!result) {
+    result = computeNextMasterSecret(false, 0, FullPage);
+  }
+  return result;
+}
+
+error_code DS2465::computeNextMasterSecretWithSwap(const SlaveSecretData & data,
+                                                   int pageNum,
+                                                   PageRegion region) {
+  error_code result = writeMemory(Scratchpad, data.data(), data.size());
+  if (!result) {
+    result = computeNextMasterSecret(true, pageNum, region);
+  }
+  return result;
+}
+
+error_code DS2465::computeWriteMac(const WriteMacData & data) const {
+  error_code result = writeMemory(Scratchpad, data.data(), data.size());
+  if (!result) {
+    result = computeWriteMac(false, false, 0, 0);
+  }
+  return result;
+}
+
+error_code DS2465::computeWriteMac(const WriteMacData & data,
+                                   Hash & mac) const {
+  error_code result = computeWriteMac(data);
+  if (!result) {
+    result = readMemory(mac.data(), mac.size());
+  }
+  return result;
+}
+
+error_code DS2465::computeAndTransmitWriteMac(const WriteMacData & data) const {
+  error_code result = computeWriteMac(data);
+  if (!result) {
+    result = writeMacBlock();
+  }
+  return result;
+}
+
+error_code DS2465::computeWriteMacWithSwap(const WriteMacData & data,
+                                           int pageNum, int segmentNum) const {
+  error_code result = writeMemory(Scratchpad, data.data(), data.size());
+  if (!result) {
+    result = computeWriteMac(false, true, pageNum, segmentNum);
+  }
+  return result;
+}
+
+error_code DS2465::computeWriteMacWithSwap(const WriteMacData & data,
+                                           int pageNum, int segmentNum,
+                                           Hash & mac) const {
+  error_code result = computeWriteMacWithSwap(data, pageNum, segmentNum);
+  if (!result) {
+    result = readMemory(mac.data(), mac.size());
+  }
+  return result;
+}
+
+error_code DS2465::computeAndTransmitWriteMacWithSwap(const WriteMacData & data,
+                                                      int pageNum,
+                                                      int segmentNum) const {
+  error_code result = computeWriteMacWithSwap(data, pageNum, segmentNum);
+  if (!result) {
+    result = writeMacBlock();
+  }
+  return result;
+}
+
+error_code DS2465::computeSlaveSecret(const SlaveSecretData & data) {
+  error_code result = writeMemory(Scratchpad, data.data(), data.size());
+  if (!result) {
+    result = computeSlaveSecret(false, 0, FullPage);
+  }
+  return result;
+}
+
+error_code DS2465::computeSlaveSecretWithSwap(const SlaveSecretData & data,
+                                              int pageNum, PageRegion region) {
+  error_code result = writeMemory(Scratchpad, data.data(), data.size());
+  if (!result) {
+    result = computeSlaveSecret(true, pageNum, region);
+  }
+  return result;
+}
+
+error_code DS2465::computeAuthMac(const AuthMacData & data) const {
+  error_code result = writeMemory(Scratchpad, data.data(), data.size());
+  if (!result) {
+    result = computeAuthMac(false, 0, FullPage);
+  }
+  return result;
+}
+
+error_code DS2465::computeAuthMac(const AuthMacData & data, Hash & mac) const {
+  error_code result = computeAuthMac(data);
+  if (!result) {
+    result = readMemory(mac.data(), mac.size());
+  }
+  return result;
+}
+
+error_code DS2465::computeAndTransmitAuthMac(const AuthMacData & data) const {
+  error_code result = computeAuthMac(data);
+  if (!result) {
+    result = writeMacBlock();
+  }
+  return result;
+}
+
+error_code DS2465::computeAuthMacWithSwap(const AuthMacData & data, int pageNum,
+                                          PageRegion region) const {
+  error_code result = writeMemory(Scratchpad, data.data(), data.size());
+  if (!result) {
+    result = computeAuthMac(true, pageNum, region);
+  }
+  return result;
+}
+
+error_code DS2465::computeAuthMacWithSwap(const AuthMacData & data, int pageNum,
+                                          PageRegion region, Hash & mac) const {
+  error_code result = computeAuthMacWithSwap(data, pageNum, region);
+  if (!result) {
+    result = readMemory(mac.data(), mac.size());
+  }
+  return result;
+}
+
+error_code DS2465::computeAndTransmitAuthMacWithSwap(const AuthMacData & data,
+                                                     int pageNum,
+                                                     PageRegion region) const {
+  error_code result = computeAuthMacWithSwap(data, pageNum, region);
+  if (!result) {
+    result = writeMacBlock();
+  }
+  return result;
+}
+
+const error_category & DS2465::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "DS2465"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case HardwareError:
+        return "Hardware Error";
+
+      case ArgumentOutOfRangeError:
+        return "Argument Out of Range Error";
+
+      default:
+        return defaultErrorMessage(condition);
+      }
+    }
+  } instance;
+  return instance;
+}
+
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS2465.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,358 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_DS2465
+#define MaximInterface_DS2465
+
+#include <MaximInterface/Links/I2CMaster.hpp>
+#include <MaximInterface/Links/OneWireMaster.hpp>
+#include <MaximInterface/Links/Sleep.hpp>
+#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/Sha256.hpp>
+
+namespace MaximInterface {
+
+/// Interface to the DS2465 1-Wire master and SHA-256 coprocessor.
+class DS2465 : public OneWireMaster {
+public:
+  enum ErrorValue { HardwareError = 1, ArgumentOutOfRangeError };
+
+  /// 1-Wire port adjustment parameters.
+  /// @note See datasheet page 13.
+  enum PortParameter {
+    tRSTL_STD,
+    tRSTL_OD,
+    tMSP_STD,
+    tMSP_OD,
+    tW0L_STD,
+    tW0L_OD,
+    tREC0,
+    RWPU,
+    tW1L_OD
+  };
+
+  /// Page region to use for swapping.
+  enum PageRegion { FullPage = 0x03, FirstHalf = 0x01, SecondHalf = 0x02 };
+
+  /// Holds the contents of a device memory segment.
+  typedef array<uint_least8_t, 4> Segment;
+
+  /// Holds the contents of a device memory page.
+  typedef array<uint_least8_t, 32> Page;
+
+  static const int memoryPages = 2;
+  static const int segmentsPerPage = Page::csize / Segment::csize;
+
+  /// Represents a DS2465 configuration.
+  class Config {
+  public:
+    /// Default construct with power-on config.
+    explicit Config(uint_least8_t readByte = optionAPU)
+        : readByte_(readByte & 0xF) {}
+
+    /// @{
+    /// 1-Wire Speed
+    bool get1WS() const { return (readByte_ & option1WS) == option1WS; }
+    void set1WS(bool new1WS) {
+      if (new1WS) {
+        readByte_ |= option1WS;
+      } else {
+        readByte_ &= ~option1WS;
+      }
+    }
+    /// @}
+
+    /// @{
+    /// Strong Pullup
+    bool getSPU() const { return (readByte_ & optionSPU) == optionSPU; }
+    void setSPU(bool newSPU) {
+      if (newSPU) {
+        readByte_ |= optionSPU;
+      } else {
+        readByte_ &= ~optionSPU;
+      }
+    }
+    /// @}
+
+    /// @{
+    /// 1-Wire Power Down
+    bool getPDN() const { return (readByte_ & optionPDN) == optionPDN; }
+    void setPDN(bool newPDN) {
+      if (newPDN) {
+        readByte_ |= optionPDN;
+      } else {
+        readByte_ &= ~optionPDN;
+      }
+    }
+    /// @}
+
+    /// @{
+    /// Active Pullup
+    bool getAPU() const { return (readByte_ & optionAPU) == optionAPU; }
+    void setAPU(bool newAPU) {
+      if (newAPU) {
+        readByte_ |= optionAPU;
+      } else {
+        readByte_ &= ~optionAPU;
+      }
+    }
+    /// @}
+
+    /// Byte representation that is read from the DS2465.
+    uint_least8_t readByte() const { return readByte_; }
+
+  private:
+    static const unsigned int option1WS = 0x8;
+    static const unsigned int optionSPU = 0x4;
+    static const unsigned int optionPDN = 0x2;
+    static const unsigned int optionAPU = 0x1;
+
+    uint_least8_t readByte_;
+  };
+
+  // Const member functions should not change the settings of the DS2465 or
+  // affect the state of the 1-Wire bus. Read pointer, scratchpad, MAC output
+  // register, and command register on the DS2465 are considered mutable.
+
+  DS2465(const Sleep & sleep, I2CMaster & i2cMaster,
+         uint_least8_t i2cAddress = 0x30)
+      : sleep(&sleep), i2cMaster(&i2cMaster), i2cAddress_(i2cAddress & 0xFE) {}
+
+  void setSleep(const Sleep & sleep) { this->sleep = &sleep; }
+  void setI2CMaster(I2CMaster & i2cMaster) { this->i2cMaster = &i2cMaster; }
+  uint_least8_t i2cAddress() const { return i2cAddress_; }
+  void setI2CAddress(uint_least8_t i2cAddress) {
+    this->i2cAddress_ = (i2cAddress & 0xFE);
+  }
+
+  /// Initialize hardware for use.
+  MaximInterface_EXPORT error_code initialize(Config config = Config());
+
+  /// Write a new configuration to the DS2465.
+  /// @param[in] config New configuration to write.
+  MaximInterface_EXPORT error_code writeConfig(Config config);
+
+  /// Write a new port configuration parameter to the DS2465.
+  /// @param[in] param Parameter to adjust.
+  /// @param[in] val New parameter value to set. Consult datasheet for value
+  /// mappings.
+  MaximInterface_EXPORT error_code writePortParameter(PortParameter param,
+                                                      int val);
+
+  // 1-Wire Master Commands
+
+  MaximInterface_EXPORT virtual error_code reset();
+  MaximInterface_EXPORT virtual error_code touchBitSetLevel(bool & sendRecvBit,
+                                                            Level afterLevel);
+  MaximInterface_EXPORT virtual error_code
+  readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+  MaximInterface_EXPORT virtual error_code
+  writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
+  MaximInterface_EXPORT virtual error_code readBlock(uint_least8_t * recvBuf,
+                                                     size_t recvLen);
+  MaximInterface_EXPORT virtual error_code
+  writeBlock(const uint_least8_t * sendBuf, size_t sendLen);
+  MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed);
+  /// @note The DS2465 only supports enabling strong pullup following a 1-Wire
+  /// read or write operation.
+  MaximInterface_EXPORT virtual error_code setLevel(Level newLevel);
+  MaximInterface_EXPORT virtual error_code triplet(TripletData & data);
+
+  // DS2465 Coprocessor Commands
+  
+  /// Read data from an EEPROM memory page.
+  /// @param pageNum Page number to read from.
+  MaximInterface_EXPORT error_code readPage(int pageNum, Page & data) const;
+
+  /// Write data to an EEPROM memory page.
+  /// @param pageNum Page number to copy to.
+  MaximInterface_EXPORT error_code writePage(int pageNum, const Page & data);
+
+  /// Write data to an EEPROM memory segment.
+  /// @param pageNum Page number to copy to.
+  /// @param segmentNum Segment number to copy to.
+  MaximInterface_EXPORT error_code writeSegment(int pageNum, int segmentNum,
+                                                const Segment & data);
+
+  /// Write data to the secret EEPROM memory page.
+  MaximInterface_EXPORT error_code
+  writeMasterSecret(const Sha256::Hash & masterSecret);
+
+  /// Compute Next Master Secret.
+  /// @param data Combined data fields for computation.
+  MaximInterface_EXPORT error_code
+  computeNextMasterSecret(const Sha256::SlaveSecretData & data);
+
+  /// Compute Next Master Secret with page swapping.
+  /// @param data Combined data fields for computation.
+  /// @param pageNum Page number to swap in.
+  /// @param region Region of the page to swap in.
+  MaximInterface_EXPORT error_code computeNextMasterSecretWithSwap(
+      const Sha256::SlaveSecretData & data, int pageNum, PageRegion region);
+
+  /// Compute Write MAC.
+  /// @param data Combined data fields for computation.
+  /// @param[out] mac Computed Write MAC.
+  MaximInterface_EXPORT error_code
+  computeWriteMac(const Sha256::WriteMacData & data, Sha256::Hash & mac) const;
+
+  /// Compute Write MAC.
+  /// @param data Combined data fields for computation.
+  MaximInterface_EXPORT error_code
+  computeAndTransmitWriteMac(const Sha256::WriteMacData & data) const;
+
+  /// Compute Write MAC with page swapping.
+  /// @param data Combined data fields for computation.
+  /// @param pageNum Page number to swap in.
+  /// @param segmentNum Segment number to swap in.
+  /// @param[out] mac Computed Write MAC.
+  MaximInterface_EXPORT error_code
+  computeWriteMacWithSwap(const Sha256::WriteMacData & data, int pageNum,
+                          int segmentNum, Sha256::Hash & mac) const;
+
+  /// Compute Write MAC with page swapping.
+  /// @param data Combined data fields for computation.
+  /// @param pageNum Page number to swap in.
+  /// @param segmentNum Segment number to swap in.
+  MaximInterface_EXPORT error_code computeAndTransmitWriteMacWithSwap(
+      const Sha256::WriteMacData & data, int pageNum, int segmentNum) const;
+
+  /// Compute Slave Secret (S-Secret).
+  /// @param data Combined data fields for computation.
+  MaximInterface_EXPORT error_code
+  computeSlaveSecret(const Sha256::SlaveSecretData & data);
+
+  /// Compute Slave Secret (S-Secret) with page swapping.
+  /// @param data Combined data fields for computation.
+  /// @param pageNum Page number to swap in.
+  /// @param region Region of the page to swap in.
+  MaximInterface_EXPORT error_code computeSlaveSecretWithSwap(
+      const Sha256::SlaveSecretData & data, int pageNum, PageRegion region);
+
+  /// Compute Authentication MAC.
+  /// @param data Combined data fields for computation.
+  /// @param[out] mac Computed Auth MAC.
+  MaximInterface_EXPORT error_code
+  computeAuthMac(const Sha256::AuthMacData & data, Sha256::Hash & mac) const;
+
+  /// Compute Authentication MAC.
+  /// @param data Combined data fields for computation.
+  MaximInterface_EXPORT error_code
+  computeAndTransmitAuthMac(const Sha256::AuthMacData & data) const;
+
+  /// Compute Authentication MAC with page swapping.
+  /// @param data Combined data fields for computation.
+  /// @param pageNum Page number to swap in.
+  /// @param region Region of the page to swap in.
+  /// @param[out] mac Computed Auth MAC.
+  MaximInterface_EXPORT error_code
+  computeAuthMacWithSwap(const Sha256::AuthMacData & data, int pageNum,
+                         PageRegion region, Sha256::Hash & mac) const;
+
+  /// Compute Authentication MAC with page swapping.
+  /// @param data Combined data fields for computation.
+  /// @param pageNum Page number to swap in.
+  /// @param region Region of the page to swap in.
+  MaximInterface_EXPORT error_code computeAndTransmitAuthMacWithSwap(
+      const Sha256::AuthMacData & data, int pageNum, PageRegion region) const;
+
+  MaximInterface_EXPORT static const error_category & errorCategory();
+
+private:
+  const Sleep * sleep;
+  I2CMaster * i2cMaster;
+  uint_least8_t i2cAddress_;
+  Config curConfig;
+
+  /// Performs a soft reset on the DS2465.
+  /// @note This is not a 1-Wire Reset.
+  error_code resetDevice();
+
+  /// Polls the DS2465 status waiting for the 1-Wire Busy bit (1WB) to be cleared.
+  /// @param[out] pStatus Optionally retrive the status byte when 1WB cleared.
+  /// @returns Success or TimeoutError if poll limit reached.
+  error_code pollBusy(uint_least8_t * pStatus = NULL) const;
+
+  /// Ensure that the desired 1-Wire level is set in the configuration.
+  /// @param level Desired 1-Wire level.
+  error_code configureLevel(Level level);
+
+  /// Const since only for internal use.
+  error_code writeMemory(uint_least8_t addr, const uint_least8_t * buf,
+                         size_t bufLen) const;
+
+  /// Read memory from the DS2465.
+  /// @param addr Address to begin reading from.
+  /// @param[out] buf Buffer to hold read data.
+  /// @param bufLen Length of buffer, buf, and number of bytes to read.
+  error_code readMemory(uint_least8_t addr, uint_least8_t * buf,
+                        size_t bufLen) const;
+
+  /// Read memory from the DS2465 at the current pointer.
+  /// @param[out] buf Buffer to hold read data.
+  /// @param bufLen Length of buffer, buf, and number of bytes to read.
+  error_code readMemory(uint_least8_t * buf, size_t bufLen) const;
+
+  /// Write the last computed MAC to the 1-Wire bus.
+  error_code writeMacBlock() const;
+
+  error_code computeWriteMac(const Sha256::WriteMacData & data) const;
+
+  error_code computeWriteMacWithSwap(const Sha256::WriteMacData & data,
+                                     int pageNum, int segmentNum) const;
+
+  error_code computeAuthMac(const Sha256::AuthMacData & data) const;
+
+  error_code computeAuthMacWithSwap(const Sha256::AuthMacData & data,
+                                    int pageNum, PageRegion region) const;
+
+  // Legacy implementations
+  error_code copyScratchpad(bool destSecret, int pageNum, bool notFull,
+                            int segmentNum);
+
+  error_code computeNextMasterSecret(bool swap, int pageNum, PageRegion region);
+
+  error_code computeWriteMac(bool regwrite, bool swap, int pageNum,
+                             int segmentNum) const;
+
+  error_code computeSlaveSecret(bool swap, int pageNum, PageRegion region);
+
+  error_code computeAuthMac(bool swap, int pageNum, PageRegion region) const;
+};
+
+inline error_code make_error_code(DS2465::ErrorValue e) {
+  return error_code(e, DS2465::errorCategory());
+}
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS2480B.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,687 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <MaximInterface/Utilities/Error.hpp>
+#include "DS2480B.hpp"
+
+// 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
+#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_dynamic 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
+
+// DS2480B program voltage available
+#define DS2480BPROG_MASK 0x20
+
+namespace MaximInterface {
+
+error_code DS2480B::initialize() {
+  // reset modes
+  level = NormalLevel;
+  baud = Baud9600bps;
+  mode = MODSEL_COMMAND;
+  speed = SPEEDSEL_FLEX;
+
+  // set the baud rate to 9600
+  error_code result = setComBaud(baud);
+  if (result) {
+    return result;
+  }
+
+  // send a break to reset the DS2480B
+  result = breakCom();
+  if (result) {
+    return result;
+  }
+
+  // delay to let line settle
+  (*sleep)(2);
+
+  // flush the buffers
+  result = uart->clearReadBuffer();
+  if (result) {
+    return result;
+  }
+
+  // send the timing byte
+  uint_least8_t packet[5];
+  packet[0] = 0xC1;
+  result = uart->writeBlock(packet, 1);
+  if (result) {
+    return result;
+  }
+
+  // delay to let line settle
+  (*sleep)(2);
+
+  // set the FLEX configuration parameters
+  // default PDSRC = 1.37Vus
+  int packetLen = 0;
+  packet[packetLen++] = CMD_CONFIG | PARMSEL_SLEW | PARMSET_Slew1p37Vus;
+  // default W1LT = 10us
+  packet[packetLen++] = CMD_CONFIG | PARMSEL_WRITE1LOW | PARMSET_Write10us;
+  // default DSO/WORT = 8us
+  packet[packetLen++] = CMD_CONFIG | PARMSEL_SAMPLEOFFSET | PARMSET_SampOff8us;
+
+  // construct the command to read the baud rate (to test command block)
+  packet[packetLen++] = CMD_CONFIG | PARMSEL_PARMREAD | (PARMSEL_BAUDRATE >> 3);
+
+  // also do 1 bit operation (to test 1-Wire block)
+  packet[packetLen++] = CMD_COMM | FUNCTSEL_BIT | baud | BITPOL_ONE;
+
+  // flush the buffers
+  result = uart->clearReadBuffer();
+  if (result) {
+    return result;
+  }
+
+  // send the packet
+  result = uart->writeBlock(packet, packetLen);
+  if (result) {
+    return result;
+  }
+
+  // read back the response
+  result = uart->readBlock(packet, sizeof(packet) / sizeof(packet[0]));
+  if (result) {
+    return result;
+  }
+
+  // look at the baud rate and bit operation
+  // to see if the response makes sense
+  if (!(((packet[3] & 0xF1) == 0x00) && ((packet[3] & 0x0E) == baud) &&
+        ((packet[4] & 0xF0) == 0x90) && ((packet[4] & 0x0C) == baud))) {
+    result = make_error_code(HardwareError);
+  }
+
+  return result;
+}
+
+error_code DS2480B::reset() {
+  uint_least8_t packet[2];
+  int packetLen = 0;
+
+  // check for correct mode
+  if (mode != MODSEL_COMMAND) {
+    mode = MODSEL_COMMAND;
+    packet[packetLen++] = MODE_COMMAND;
+  }
+
+  // construct the command
+  packet[packetLen++] = (CMD_COMM | FUNCTSEL_RESET | speed);
+
+  // flush the buffers
+  error_code result = uart->clearReadBuffer();
+  if (result) {
+    return result;
+  }
+
+  // send the packet
+  result = uart->writeBlock(packet, packetLen);
+  if (result) {
+    return result;
+  }
+
+  // read back the 1 byte response
+  result = uart->readBlock(packet, 1);
+  if (result) {
+    return result;
+  }
+
+  // make sure this byte looks like a reset byte
+  if ((packet[0] & RB_RESET_MASK) == RB_1WIRESHORT) {
+    result = make_error_code(ShortDetectedError);
+  }
+  else if ((packet[0] & RB_RESET_MASK) == RB_NOPRESENCE) {
+    result = make_error_code(NoSlaveError);
+  }
+
+  return result;
+}
+
+error_code DS2480B::touchBitSetLevel(bool & sendRecvBit, Level afterLevel) {
+  uint_least8_t packet[2];
+  int packetLen = 0;
+
+  // check for correct mode
+  if (mode != MODSEL_COMMAND) {
+    mode = MODSEL_COMMAND;
+    packet[packetLen++] = MODE_COMMAND;
+  }
+
+  // construct the command
+  packet[packetLen++] = (sendRecvBit ? BITPOL_ONE : BITPOL_ZERO) | CMD_COMM |
+                        FUNCTSEL_BIT | speed;
+
+  // flush the buffers
+  error_code result = uart->clearReadBuffer();
+  if (result) {
+    return result;
+  }
+
+  // send the packet
+  result = uart->writeBlock(packet, packetLen);
+  if (result) {
+    return result;
+  }
+
+  // read back the response
+  result = uart->readBlock(packet, 1);
+  if (result) {
+    return result;
+  }
+
+  // interpret the response
+  if ((packet[0] & 0xE0) == 0x80) {
+    sendRecvBit = ((packet[0] & RB_BIT_MASK) == RB_BIT_ONE);
+    result = setLevel(afterLevel);
+  } else {
+    result = make_error_code(HardwareError);
+  }
+
+  return result;
+}
+
+error_code DS2480B::writeByteSetLevel(uint_least8_t sendByte,
+                                      Level afterLevel) {
+  uint_least8_t packet[3];
+  int packetLen = 0;
+
+  // check for correct mode
+  if (mode != MODSEL_DATA) {
+    mode = MODSEL_DATA;
+    packet[packetLen++] = MODE_DATA;
+  }
+
+  // add the byte to send
+  packet[packetLen++] = sendByte;
+
+  // check for duplication of data that looks like COMMAND mode
+  if (sendByte == MODE_COMMAND) {
+    packet[packetLen++] = sendByte;
+  }
+
+  // flush the buffers
+  error_code result = uart->clearReadBuffer();
+  if (result) {
+    return result;
+  }
+
+  // send the packet
+  result = uart->writeBlock(packet, packetLen);
+  if (result) {
+    return result;
+  }
+
+  // read back the 1 byte response
+  result = uart->readBlock(packet, 1);
+  if (result) {
+    return result;
+  }
+
+  if (packet[0] == sendByte) {
+    result = setLevel(afterLevel);
+  } else {
+    result = make_error_code(HardwareError);
+  }
+
+  return result;
+}
+
+error_code DS2480B::readByteSetLevel(uint_least8_t & recvByte,
+                                     Level afterLevel) {
+  uint_least8_t packet[2];
+  int packetLen = 0;
+
+  // check for correct mode
+  if (mode != MODSEL_DATA) {
+    mode = MODSEL_DATA;
+    packet[packetLen++] = MODE_DATA;
+  }
+
+  // add the byte to send
+  packet[packetLen++] = 0xFF;
+
+  // flush the buffers
+  error_code result = uart->clearReadBuffer();
+  if (result) {
+    return result;
+  }
+
+  // send the packet
+  result = uart->writeBlock(packet, packetLen);
+  if (result) {
+    return result;
+  }
+
+  // read back the 1 byte response
+  result = uart->readBlock(packet, 1);
+  if (result) {
+    return result;
+  }
+
+  recvByte = packet[0];
+  result = setLevel(afterLevel);
+
+  return result;
+}
+
+error_code DS2480B::setSpeed(Speed newSpeed) {
+  error_code result;
+  bool setSpeed = false;
+
+  // check if supported speed
+  switch (newSpeed) {
+  case OverdriveSpeed:
+    // check if change from current mode
+    if (speed != SPEEDSEL_OD) {
+      result = changeBaud(Baud115200bps);
+      if (!result) {
+        speed = SPEEDSEL_OD;
+        setSpeed = true;
+      }
+    }
+    break;
+
+  case StandardSpeed:
+    // check if change from current mode
+    if (speed != SPEEDSEL_STD) {
+      result = changeBaud(Baud9600bps);
+      if (!result) {
+        speed = SPEEDSEL_STD;
+        setSpeed = true;
+      }
+    }
+    break;
+
+  default:
+    result = make_error_code(InvalidSpeedError);
+    break;
+  }
+
+  // if baud rate is set correctly then change DS2480 speed
+  if (setSpeed) {
+    uint_least8_t packet[2];
+    int packetLen = 0;
+
+    // check if correct mode
+    if (mode != MODSEL_COMMAND) {
+      mode = MODSEL_COMMAND;
+      packet[packetLen++] = MODE_COMMAND;
+    }
+
+    // proceed to set the DS2480 communication speed
+    packet[packetLen++] = CMD_COMM | FUNCTSEL_SEARCHOFF | speed;
+
+    // send the packet
+    result = uart->writeBlock(packet, packetLen);
+  }
+
+  return result;
+}
+
+error_code DS2480B::setLevel(Level newLevel) {
+  error_code result;
+  // check if need to change level
+  if (newLevel != level) {
+    uint_least8_t packet[4];
+    int packetLen = 0;
+
+    // check for correct mode
+    if (mode != MODSEL_COMMAND) {
+      mode = MODSEL_COMMAND;
+      packet[packetLen++] = MODE_COMMAND;
+    }
+
+    switch (newLevel) {
+    case NormalLevel:
+      // stop pulse command
+      packet[packetLen++] = MODE_STOP_PULSE;
+
+      // add the command to begin the pulse WITHOUT prime
+      packet[packetLen++] = CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE |
+                            BITPOL_5V | PRIME5V_FALSE;
+
+      // stop pulse command
+      packet[packetLen++] = MODE_STOP_PULSE;
+
+      // flush the buffers
+      result = uart->clearReadBuffer();
+      if (result) {
+        return result;
+      }
+
+      // send the packet
+      result = uart->writeBlock(packet, packetLen);
+      if (result) {
+        return result;
+      }
+
+      // read back the 1 byte response
+      result = uart->readBlock(packet, 2);
+      if (result) {
+        return result;
+      }
+
+      // check response byte
+      if (((packet[0] & 0xE0) == 0xE0) && ((packet[1] & 0xE0) == 0xE0)) {
+        level = NormalLevel;
+      } else {
+        result = make_error_code(HardwareError);
+      }
+      break;
+
+    case StrongLevel:
+      // set the SPUD time value
+      packet[packetLen++] = CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite;
+      // add the command to begin the pulse
+      packet[packetLen++] =
+          CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V;
+
+      // flush the buffers
+      result = uart->clearReadBuffer();
+      if (result) {
+        return result;
+      }
+
+      // send the packet
+      result = uart->writeBlock(packet, packetLen);
+      if (result) {
+        return result;
+      }
+
+      // read back the 1 byte response from setting time limit
+      result = uart->readBlock(packet, 1);
+      if (result) {
+        return result;
+      }
+
+      // check response byte
+      if ((packet[0] & 0x81) == 0) {
+        level = newLevel;
+      } else {
+        result = make_error_code(HardwareError);
+      }
+      break;
+
+    default:
+      result = make_error_code(InvalidLevelError);
+      break;
+    }
+  }
+  return result;
+}
+
+error_code DS2480B::changeBaud(BaudRate newBaud) {
+  error_code result;
+
+  //see if different then current baud rate
+  if (baud != newBaud) {
+    uint_least8_t packet[2];
+    int packetLen = 0;
+
+    // build the command packet
+    // check for correct mode
+    if (mode != MODSEL_COMMAND) {
+      mode = MODSEL_COMMAND;
+      packet[packetLen++] = MODE_COMMAND;
+    }
+    // build the command
+    const uint_least8_t baudByte = CMD_CONFIG | PARMSEL_BAUDRATE | newBaud;
+    packet[packetLen++] = baudByte;
+
+    // flush the buffers
+    result = uart->clearReadBuffer();
+    if (result) {
+      return result;
+    }
+
+    // send the packet
+    result = uart->writeBlock(packet, packetLen);
+    if (result) {
+      return result;
+    }
+
+    // make sure buffer is flushed
+    (*sleep)(5);
+
+    // change our baud rate
+    result = setComBaud(newBaud);
+    if (result) {
+      return result;
+    }
+    baud = newBaud;
+
+    // wait for things to settle
+    (*sleep)(5);
+
+    // build a command packet to read back baud rate
+    packet[0] = CMD_CONFIG | PARMSEL_PARMREAD | (PARMSEL_BAUDRATE >> 3);
+
+    // flush the buffers
+    result = uart->clearReadBuffer();
+    if (result) {
+      return result;
+    }
+
+    // send the packet
+    result = uart->writeBlock(packet, 1);
+    if (result) {
+      return result;
+    }
+
+    // read back the 1 byte response
+    result = uart->readBlock(packet, 1);
+    if (result) {
+      return result;
+    }
+
+    // verify correct baud
+    if (!((packet[0] & 0x0E) == (baudByte & 0x0E))) {
+      result = make_error_code(HardwareError);
+    }
+  }
+
+  return result;
+}
+
+error_code DS2480B::setComBaud(BaudRate newBaud) {
+  switch (newBaud) {
+  case Baud115200bps:
+    return uart->setBaud(115200);
+
+  case Baud57600bps:
+    return uart->setBaud(57600);
+
+  case Baud19200bps:
+    return uart->setBaud(19200);
+
+  case Baud9600bps:
+  default:
+    return uart->setBaud(9600);
+  }
+}
+
+error_code DS2480B::breakCom() {
+  // Switch to lower baud rate to ensure break is longer than 2 ms.
+  error_code result = uart->setBaud(4800);
+  if (result) {
+    return result;
+  }
+  result = uart->sendBreak();
+  if (result) {
+    return result;
+  }
+  result = setComBaud(baud);
+  return result;
+}
+
+const error_category & DS2480B::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "DS2480B"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case HardwareError:
+        return "Hardware Error";
+
+      default:
+        return defaultErrorMessage(condition);
+      }
+    }
+  } instance;
+  return instance;
+}
+
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS2480B.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,97 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_DS2480B
+#define MaximInterface_DS2480B
+
+#include <MaximInterface/Links/OneWireMaster.hpp>
+#include <MaximInterface/Links/Sleep.hpp>
+#include <MaximInterface/Links/Uart.hpp>
+#include <MaximInterface/Utilities/Export.h>
+
+namespace MaximInterface {
+
+/// Serial to 1-Wire Line Driver
+class DS2480B : public OneWireMaster {
+public:
+  enum ErrorValue {
+    HardwareError = 1,
+  };
+
+  DS2480B(const Sleep & sleep, Uart & uart) : sleep(&sleep), uart(&uart) {}
+
+  void setSleep(const Sleep & sleep) { this->sleep = &sleep; }
+  void setUart(Uart & uart) { this->uart = &uart; }
+
+  MaximInterface_EXPORT error_code initialize();
+
+  MaximInterface_EXPORT virtual error_code reset();
+  MaximInterface_EXPORT virtual error_code touchBitSetLevel(bool & sendRecvBit,
+                                                            Level afterLevel);
+  MaximInterface_EXPORT virtual error_code
+  writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
+  MaximInterface_EXPORT virtual error_code
+  readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+  MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed);
+  MaximInterface_EXPORT virtual error_code setLevel(Level newLevel);
+
+  MaximInterface_EXPORT static const error_category & errorCategory();
+
+private:
+  /// Baud rates for DS2480B
+  enum BaudRate {
+    Baud9600bps = 0,  ///< 9600 bps
+    Baud19200bps = 2, ///< 19200 bps
+    Baud57600bps = 4, ///< 57600 bps
+    Baud115200bps = 6 ///< 115200 bps
+  };
+
+  error_code changeBaud(BaudRate newBaud);
+  error_code setComBaud(BaudRate newBaud);
+  error_code breakCom();
+
+  const Sleep * sleep;
+  Uart * uart;
+
+  Level level;
+  BaudRate baud;
+  uint_least8_t mode;
+  uint_least8_t speed;
+};
+
+inline error_code make_error_code(DS2480B::ErrorValue e) {
+  return error_code(e, DS2480B::errorCategory());
+}
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS2482_DS2484.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,449 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <MaximInterface/Utilities/Error.hpp>
+#include "DS2482_DS2484.hpp"
+
+namespace MaximInterface {
+
+enum Command {
+  DeviceResetCmd = 0xF0,
+  WriteDeviceConfigCmd = 0xD2,
+  AdjustOwPortCmd = 0xC3,  // DS2484 only
+  ChannelSelectCmd = 0xC3, // DS2482-800 only
+  SetReadPointerCmd = 0xE1,
+  OwResetCmd = 0xB4,
+  OwWriteByteCmd = 0xA5,
+  OwReadByteCmd = 0x96,
+  OwSingleBitCmd = 0x87,
+  OwTripletCmd = 0x78
+};
+
+// Device register pointers.
+enum Register {
+  ConfigReg = 0xC3,
+  StatusReg = 0xF0,
+  ReadDataReg = 0xE1
+};
+
+// Device Status bits
+enum StatusBit {
+  Status_1WB = 0x01,
+  Status_PPD = 0x02,
+  Status_SD = 0x04,
+  Status_LL = 0x08,
+  Status_RST = 0x10,
+  Status_SBR = 0x20,
+  Status_TSB = 0x40,
+  Status_DIR = 0x80
+};
+
+error_code DS2482_DS2484::initialize(Config config) {
+  // reset device
+  error_code result = resetDevice();
+  if (result) {
+    return result;
+  }
+
+  // write the default configuration setup
+  result = writeConfig(config);
+  return result;
+}
+
+error_code DS2482_DS2484::resetDevice() {
+  // Device Reset
+  //   S AD,0 [A] DRST [A] Sr AD,1 [A] [SS] A\ P
+  //  [] indicates from slave
+  //  SS status byte to read to verify state
+
+  uint_least8_t buf;
+  error_code result = sendCommand(DeviceResetCmd);
+
+  if (!result) {
+    result = readRegister(buf);
+  }
+
+  if (!result) {
+    if ((buf & 0xF7) != 0x10) {
+      result = make_error_code(HardwareError);
+    }
+  }
+
+  if (!result) {
+    reset(); // do a command to get 1-Wire master reset out of holding state
+  }
+
+  return result;
+}
+
+error_code DS2482_DS2484::triplet(TripletData & data) {
+  // 1-Wire Triplet (Case B)
+  //   S AD,0 [A] 1WT [A] SS [A] Sr AD,1 [A] [Status] A [Status] A\ P
+  //                                         \--------/
+  //                           Repeat until 1WB bit has changed to 0
+  //  [] indicates from slave
+  //  SS indicates byte containing search direction bit value in msbit
+
+  error_code result = sendCommand(OwTripletCmd, data.writeBit ? 0x80 : 0x00);
+  if (!result) {
+    uint_least8_t status;
+    result = pollBusy(&status);
+    if (!result) {
+      // check bit results in status byte
+      data.readBit = ((status & Status_SBR) == Status_SBR);
+      data.readBitComplement = ((status & Status_TSB) == Status_TSB);
+      data.writeBit = ((status & Status_DIR) == Status_DIR);
+    }
+  }
+  return result;
+}
+
+error_code DS2482_DS2484::reset() {
+  // 1-Wire reset (Case B)
+  //   S AD,0 [A] 1WRS [A] Sr AD,1 [A] [Status] A [Status] A\ P
+  //                                   \--------/
+  //                       Repeat until 1WB bit has changed to 0
+  //  [] indicates from slave
+
+  error_code result = sendCommand(OwResetCmd);
+  uint_least8_t buf;
+
+  if (!result) {
+    result = pollBusy(&buf);
+  }
+
+  if (!result) {
+    if ((buf & Status_SD) == Status_SD) {
+      result = make_error_code(ShortDetectedError);
+    }
+    else if ((buf & Status_PPD) != Status_PPD) {
+      result = make_error_code(NoSlaveError);
+    }
+  }
+
+  return result;
+}
+
+error_code DS2482_DS2484::touchBitSetLevel(bool & sendRecvBit, Level afterLevel) {
+  // 1-Wire bit (Case B)
+  //   S AD,0 [A] 1WSB [A] BB [A] Sr AD,1 [A] [Status] A [Status] A\ P
+  //                                          \--------/
+  //                           Repeat until 1WB bit has changed to 0
+  //  [] indicates from slave
+  //  BB indicates byte containing bit value in msbit
+
+  error_code result = configureLevel(afterLevel);
+
+  if (!result) {
+    result = sendCommand(OwSingleBitCmd, sendRecvBit ? 0x80 : 0x00);
+  }
+
+  uint_least8_t status;
+
+  if (!result) {
+    result = pollBusy(&status);
+  }
+
+  if (!result) {
+    sendRecvBit = ((status & Status_SBR) == Status_SBR);
+  }
+
+  return result;
+}
+
+error_code DS2482_DS2484::writeByteSetLevel(uint_least8_t sendByte, Level afterLevel) {
+  // 1-Wire Write Byte (Case B)
+  //   S AD,0 [A] 1WWB [A] DD [A] Sr AD,1 [A] [Status] A [Status] A\ P
+  //                                          \--------/
+  //                             Repeat until 1WB bit has changed to 0
+  //  [] indicates from slave
+  //  DD data to write
+
+  error_code result = configureLevel(afterLevel);
+  if (result) {
+    return result;
+  }
+
+  result = sendCommand(OwWriteByteCmd, sendByte);
+  if (!result) {
+    result = pollBusy();
+  }
+
+  return result;
+}
+
+error_code DS2482_DS2484::readByteSetLevel(uint_least8_t & recvByte,
+                                    Level afterLevel) {
+  // 1-Wire Read Bytes (Case C)
+  //   S AD,0 [A] 1WRB [A] Sr AD,1 [A] [Status] A [Status] A
+  //                                   \--------/
+  //                     Repeat until 1WB bit has changed to 0
+  //   Sr AD,0 [A] SRP [A] E1 [A] Sr AD,1 [A] DD A\ P
+  //
+  //  [] indicates from slave
+  //  DD data read
+
+  error_code result = configureLevel(afterLevel);
+  if (result) {
+    return result;
+  }
+
+  result = sendCommand(OwReadByteCmd);
+
+  if (!result) {
+    result = pollBusy();
+  }
+
+  uint_least8_t buf;
+
+  if (!result) {
+    result = readRegister(ReadDataReg, buf);
+  }
+
+  if (!result) {
+    recvByte = buf;
+  }
+
+  return result;
+}
+
+error_code DS2482_DS2484::setSpeed(Speed newSpeed) {
+  // Check if supported speed
+  if (!((newSpeed == OverdriveSpeed) || (newSpeed == StandardSpeed))) {
+    return make_error_code(InvalidSpeedError);
+  }
+  // Check if requested speed is already set
+  if (curConfig.get1WS() == (newSpeed == OverdriveSpeed)) {
+    return error_code();
+  }
+  // Set the speed
+  Config newConfig = curConfig;
+  newConfig.set1WS(newSpeed == OverdriveSpeed);
+  return writeConfig(newConfig);
+}
+
+error_code DS2482_DS2484::setLevel(Level newLevel) {
+  if (newLevel == StrongLevel) {
+    return make_error_code(InvalidLevelError);
+  }
+
+  return configureLevel(newLevel);
+}
+
+error_code DS2482_DS2484::writeConfig(Config config) {
+  uint_least8_t configBuf = ((config.readByte() ^ 0xF) << 4) | config.readByte();
+  error_code result = sendCommand(WriteDeviceConfigCmd, configBuf);
+  if (!result) {
+    result = readRegister(ConfigReg, configBuf);
+  }
+  if (!result) {
+    if (configBuf != config.readByte()) {
+      result = make_error_code(HardwareError);
+    }
+  }
+  if (!result) {
+    curConfig = config;
+  }
+  return result;
+}
+
+error_code DS2482_DS2484::readRegister(uint_least8_t reg, uint_least8_t & buf) const {
+  error_code result = sendCommand(SetReadPointerCmd, reg);
+  if (!result) {
+    result = readRegister(buf);
+  }
+  return result;
+}
+
+error_code DS2482_DS2484::readRegister(uint_least8_t & buf) const {
+  return i2cMaster->readPacket(i2cAddress_, &buf, 1);
+}
+
+error_code DS2482_DS2484::pollBusy(uint_least8_t * pStatus) {
+  const int pollLimit = 200;
+
+  int pollCount = 0;
+  uint_least8_t status;
+  do {
+    error_code result = readRegister(status);
+    if (result) {
+      return result;
+    }
+    if (pStatus != NULL) {
+      *pStatus = status;
+    }
+    if (pollCount++ >= pollLimit) {
+      return make_error_code(HardwareError);
+    }
+  } while (status & Status_1WB);
+
+  return error_code();
+}
+
+error_code DS2482_DS2484::configureLevel(Level level) {
+  // Check if supported level
+  if (!((level == NormalLevel) || (level == StrongLevel))) {
+    return make_error_code(InvalidLevelError);
+  }
+  // Check if requested level already set
+  if (curConfig.getSPU() == (level == StrongLevel)) {
+    return error_code();
+  }
+  // Set the level
+  Config newConfig = curConfig;
+  newConfig.setSPU(level == StrongLevel);
+  return writeConfig(newConfig);
+}
+
+error_code DS2482_DS2484::sendCommand(uint_least8_t cmd) const {
+  return i2cMaster->writePacket(i2cAddress_, &cmd, 1);
+}
+
+error_code DS2482_DS2484::sendCommand(uint_least8_t cmd, uint_least8_t param) const {
+  uint_least8_t buf[] = {cmd, param};
+  return i2cMaster->writePacket(i2cAddress_, buf, sizeof(buf) / sizeof(buf[0]));
+}
+
+const error_category & DS2482_DS2484::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "DS2482_DS2484"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case HardwareError:
+        return "Hardware Error";
+
+      case ArgumentOutOfRangeError:
+        return "Argument Out of Range Error";
+
+      default:
+        return defaultErrorMessage(condition);
+      }
+    }
+  } instance;
+  return instance;
+}
+
+error_code DS2482_800::selectChannel(int channel) {
+  // Channel Select (Case A)
+  //   S AD,0 [A] CHSL [A] CC [A] Sr AD,1 [A] [RR] A\ P
+  //  [] indicates from slave
+  //  CC channel value
+  //  RR channel read back
+
+  uint_least8_t ch;
+  uint_least8_t ch_read;
+  switch (channel) {
+  case 0:
+    ch = 0xF0;
+    ch_read = 0xB8;
+    break;
+
+  case 1:
+    ch = 0xE1;
+    ch_read = 0xB1;
+    break;
+
+  case 2:
+    ch = 0xD2;
+    ch_read = 0xAA;
+    break;
+
+  case 3:
+    ch = 0xC3;
+    ch_read = 0xA3;
+    break;
+
+  case 4:
+    ch = 0xB4;
+    ch_read = 0x9C;
+    break;
+
+  case 5:
+    ch = 0xA5;
+    ch_read = 0x95;
+    break;
+
+  case 6:
+    ch = 0x96;
+    ch_read = 0x8E;
+    break;
+
+  case 7:
+    ch = 0x87;
+    ch_read = 0x87;
+    break;
+
+  default:
+    return make_error_code(ArgumentOutOfRangeError);
+  };
+
+  error_code result = sendCommand(ChannelSelectCmd, ch);
+  if (!result) {
+    result = readRegister(ch);
+    if (!result) {
+      // check for failure due to incorrect read back of channel
+      if (ch != ch_read) {
+        result = make_error_code(HardwareError);
+      }
+    }
+  }
+
+  return result;
+}
+
+error_code DS2484::adjustPort(PortParameter param, int val) {
+  if (val < 0 || val > 15) {
+    return make_error_code(ArgumentOutOfRangeError);
+  }
+
+  error_code result = sendCommand(AdjustOwPortCmd, (param << 4) | val);
+  if (result) {
+    return result;
+  }
+
+  uint_least8_t portConfig;
+  for (int paramNum = param + 1; paramNum > 0; paramNum--) {
+    result = readRegister(portConfig);
+    if (result) {
+      return result;
+    }
+  }
+  if (val != portConfig) {
+    result = make_error_code(HardwareError);
+  }
+
+  return result;
+}
+
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS2482_DS2484.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,228 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_DS2482_DS2484
+#define MaximInterface_DS2482_DS2484
+
+#include <MaximInterface/Links/OneWireMaster.hpp>
+#include <MaximInterface/Links/I2CMaster.hpp>
+#include <MaximInterface/Utilities/Export.h>
+
+namespace MaximInterface {
+
+/// Interface to the DS2484, DS2482-100, DS2482-101, DS2482-800 1-Wire masters.
+class DS2482_DS2484 : public OneWireMaster {
+public:
+  enum ErrorValue { HardwareError = 1, ArgumentOutOfRangeError };
+
+  /// Represents a device configuration.
+  class Config {
+  public:
+    /// Default construct with power-on config.
+    explicit Config(uint_least8_t readByte = optionAPU)
+        : readByte_(readByte & 0xF) {}
+
+    /// @{
+    /// 1-Wire Speed
+    bool get1WS() const { return (readByte_ & option1WS) == option1WS; }
+    void set1WS(bool new1WS) {
+      if (new1WS) {
+        readByte_ |= option1WS;
+      } else {
+        readByte_ &= ~option1WS;
+      }
+    }
+    /// @}
+
+    /// @{
+    /// Strong Pullup
+    bool getSPU() const { return (readByte_ & optionSPU) == optionSPU; }
+    void setSPU(bool newSPU) {
+      if (newSPU) {
+        readByte_ |= optionSPU;
+      } else {
+        readByte_ &= ~optionSPU;
+      }
+    }
+    /// @}
+
+    /// @{
+    /// 1-Wire Power Down
+    bool getPDN() const { return (readByte_ & optionPDN) == optionPDN; }
+    void setPDN(bool newPDN) {
+      if (newPDN) {
+        readByte_ |= optionPDN;
+      } else {
+        readByte_ &= ~optionPDN;
+      }
+    }
+    /// @}
+
+    /// @{
+    /// Active Pullup
+    bool getAPU() const { return (readByte_ & optionAPU) == optionAPU; }
+    void setAPU(bool newAPU) {
+      if (newAPU) {
+        readByte_ |= optionAPU;
+      } else {
+        readByte_ &= ~optionAPU;
+      }
+    }
+    /// @}
+
+    /// Byte representation that is read from the device.
+    uint_least8_t readByte() const { return readByte_; }
+
+  private:
+    static const unsigned int option1WS = 0x8;
+    static const unsigned int optionSPU = 0x4;
+    static const unsigned int optionPDN = 0x2;
+    static const unsigned int optionAPU = 0x1;
+
+    uint_least8_t readByte_;
+  };
+
+  void setI2CMaster(I2CMaster & i2cMaster) { this->i2cMaster = &i2cMaster; }
+  uint_least8_t i2cAddress() const { return i2cAddress_; }
+  void setI2CAddress(uint_least8_t i2cAddress) {
+    this->i2cAddress_ = i2cAddress;
+  }
+
+  /// Initialize hardware for use.
+  MaximInterface_EXPORT error_code initialize(Config config = Config());
+
+  /// Write a new configuration to the device.
+  /// @param[in] config New configuration to write.
+  MaximInterface_EXPORT error_code writeConfig(Config config);
+
+  /// @note Perform a 1-Wire triplet using the device command.
+  MaximInterface_EXPORT virtual error_code triplet(TripletData & data);
+
+  MaximInterface_EXPORT virtual error_code reset();
+  MaximInterface_EXPORT virtual error_code touchBitSetLevel(bool & sendRecvBit,
+                                                            Level afterLevel);
+  MaximInterface_EXPORT virtual error_code
+  readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+  MaximInterface_EXPORT virtual error_code
+  writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
+  MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed);
+  MaximInterface_EXPORT virtual error_code setLevel(Level newLevel);
+
+  MaximInterface_EXPORT static const error_category & errorCategory();
+
+protected:
+  DS2482_DS2484(I2CMaster & i2cMaster, uint_least8_t i2cAddress)
+      : i2cMaster(&i2cMaster), i2cAddress_(i2cAddress) {}
+
+  /// @note Allow marking const since not public.
+  error_code sendCommand(uint_least8_t cmd) const;
+
+  /// @note Allow marking const since not public.
+  error_code sendCommand(uint_least8_t cmd, uint_least8_t param) const;
+
+  /// Reads a register from the device.
+  /// @param reg Register to read from.
+  /// @param[out] buf Buffer to hold read data.
+  error_code readRegister(uint_least8_t reg, uint_least8_t & buf) const;
+
+  /// Reads the current register from the device.
+  /// @param[out] buf Buffer to hold read data.
+  error_code readRegister(uint_least8_t & buf) const;
+
+private:
+  /// Performs a soft reset on the device.
+  /// @note This is not a 1-Wire Reset.
+  error_code resetDevice();
+
+  /// Polls the device status waiting for the 1-Wire Busy bit (1WB) to be cleared.
+  /// @param[out] pStatus Optionally retrieve the status byte when 1WB cleared.
+  /// @returns Success or TimeoutError if poll limit reached.
+  error_code pollBusy(uint_least8_t * pStatus = NULL);
+
+  /// Ensure that the desired 1-Wire level is set in the configuration.
+  /// @param level Desired 1-Wire level.
+  error_code configureLevel(Level level);
+
+  I2CMaster * i2cMaster;
+  uint_least8_t i2cAddress_;
+  Config curConfig;
+};
+
+inline error_code make_error_code(DS2482_DS2484::ErrorValue e) {
+  return error_code(e, DS2482_DS2484::errorCategory());
+}
+
+class DS2482_100 : public DS2482_DS2484 {
+public:
+  DS2482_100(I2CMaster & i2c_bus, uint_least8_t adrs)
+      : DS2482_DS2484(i2c_bus, adrs) {}
+};
+
+/// DS2482-800 I2C to 1-Wire Master
+class DS2482_800 : public DS2482_DS2484 {
+public:
+  DS2482_800(I2CMaster & i2c_bus, uint_least8_t adrs)
+      : DS2482_DS2484(i2c_bus, adrs) {}
+
+  /// Select the active 1-Wire channel.
+  /// @param channel Channel number to select from 0 to 7.
+  MaximInterface_EXPORT error_code selectChannel(int channel);
+};
+
+/// DS2484 I2C to 1-Wire Master
+class DS2484 : public DS2482_DS2484 {
+public:
+  /// 1-Wire port adjustment parameters.
+  /// @note See datasheet page 13.
+  enum PortParameter {
+    tRSTL = 0,
+    tRSTL_OD,
+    tMSP,
+    tMSP_OD,
+    tW0L,
+    tW0L_OD,
+    tREC0,   // OD N/A
+    RWPU = 8 // OD N/A
+  };
+
+  explicit DS2484(I2CMaster & i2c_bus, uint_least8_t adrs = 0x30)
+      : DS2482_DS2484(i2c_bus, adrs) {}
+
+  /// Adjust 1-Wire port parameters.
+  /// @param param Parameter to adjust.
+  /// @param val New parameter value to set. Consult datasheet for value mappings.
+  MaximInterface_EXPORT error_code adjustPort(PortParameter param, int val);
+};
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS28C36_DS2476.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,805 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <MaximInterface/Links/I2CMaster.hpp>
+#include <MaximInterface/Utilities/Error.hpp>
+#include <MaximInterface/Utilities/RomId.hpp>
+#include "DS28C36_DS2476.hpp"
+
+using std::copy;
+using std::vector;
+
+namespace MaximInterface {
+
+using namespace Ecc256;
+
+// DS28C36 commands.
+enum Command {
+  WriteMemory = 0x96,
+  ReadMemory = 0x69,
+  WriteBuffer = 0x87,
+  ReadBuffer = 0x5A,
+  ReadPageProtection = 0xAA,
+  SetPageProtection = 0xC3,
+  DecrementCounter = 0xC9,
+  ReadRng = 0xD2,
+  EncryptedReadMemory = 0x4B,
+  ComputeAndReadPathAuthentication = 0xA5,
+  AuthenticatedSha2WriteMemory = 0x99,
+  ComputeAndLockSha2Secret = 0x3C,
+  GenerateEcc256KeyPair = 0xCB,
+  ComputeMultiblockHash = 0x33,
+  VerifyEcdsaSignature = 0x59,
+  AuthenticateEcdsaPublicKey = 0xA8,
+  AuthenticatedEcdsaWriteMemory = 0x89
+};
+
+static error_code convertResultByte(uint_least8_t resultByte) {
+  error_code errorCode;
+  if (resultByte != 0xAA) {
+    errorCode.assign((resultByte == 0x00)
+                         ? static_cast<int>(DS28C36::AuthenticationError)
+                         : resultByte,
+                     DS28C36::errorCategory());
+  }
+  return errorCode;
+}
+
+error_code DS28C36::writeMemory(int pageNum, const Page & page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  vector<uint_least8_t> buffer;
+  buffer.reserve(1 + page.size());
+  buffer.push_back(pageNum);
+  buffer.insert(buffer.end(), page.begin(), page.end());
+  error_code result = writeCommand(WriteMemory, &buffer[0], buffer.size());
+  if (!result) {
+    sleep(writeMemoryTimeMs);
+    result = readResponse(buffer);
+    if (!result) {
+      if (buffer.size() == 1) {
+        result = convertResultByte(buffer[0]);
+      } else {
+        result = make_error_code(InvalidResponseError);
+      }
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::readMemory(int pageNum, Page & page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  vector<uint_least8_t> buffer;
+  buffer.push_back(pageNum);
+  error_code result = writeCommand(ReadMemory, &buffer[0], buffer.size());
+  if (!result) {
+    sleep(readMemoryTimeMs);
+    result = readResponse(buffer);
+    if (!result) {
+      if (buffer.size() == (1 + page.size())) {
+        result = convertResultByte(buffer[0]);
+        copy(buffer.begin() + 1, buffer.end(), page.begin());
+      } else {
+        result = make_error_code(InvalidResponseError);
+      }
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::writeBuffer(const uint_least8_t * data, size_t dataSize) {
+  return writeCommand(WriteBuffer, data, dataSize);
+}
+
+error_code DS28C36::readBuffer(vector<uint_least8_t> & data) {
+  error_code result = writeCommand(ReadBuffer, NULL, 0);
+  if (!result) {
+    result = readResponse(data);
+  }
+  return result;
+}
+
+error_code DS28C36::readPageProtection(int pageNum,
+                                       PageProtection & protection) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  vector<uint_least8_t> buffer;
+  buffer.push_back(pageNum);
+  error_code result =
+      writeCommand(ReadPageProtection, &buffer[0], buffer.size());
+  if (!result) {
+    sleep(readMemoryTimeMs);
+    result = readResponse(buffer);
+    if (!result) {
+      if (buffer.size() == 1) {
+        protection = buffer[0];
+      } else {
+        result = make_error_code(InvalidResponseError);
+      }
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::setPageProtection(int pageNum,
+                                      const PageProtection & protection) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  vector<uint_least8_t> buffer;
+  buffer.push_back(pageNum);
+  buffer.push_back(static_cast<uint_least8_t>(protection.to_ulong()));
+  error_code result =
+      writeCommand(SetPageProtection, &buffer[0], buffer.size());
+  if (!result) {
+    sleep(writeMemoryTimeMs);
+    result = readResponse(buffer);
+    if (!result) {
+      if (buffer.size() == 1) {
+        result = convertResultByte(buffer[0]);
+      } else {
+        result = make_error_code(InvalidResponseError);
+      }
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::decrementCounter() {
+  error_code result = writeCommand(DecrementCounter, NULL, 0);
+  if (!result) {
+    sleep(writeMemoryTimeMs);
+    vector<uint_least8_t> buffer;
+    result = readResponse(buffer);
+    if (!result) {
+      if (buffer.size() == 1) {
+        result = convertResultByte(buffer[0]);
+      } else {
+        result = make_error_code(InvalidResponseError);
+      }
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::readRng(int numBytes, vector<uint_least8_t> & data) {
+  if ((numBytes < 1) || (numBytes > 64)) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  data.clear();
+  data.push_back(numBytes - 1);
+  error_code result = writeCommand(ReadRng, &data[0], data.size());
+  if (!result) {
+    sleep(sha256ComputationTimeMs);
+    result = readResponse(data);
+    if (!result) {
+      if (data.size() !=
+          static_cast<vector<uint_least8_t>::size_type>(numBytes)) {
+        result = make_error_code(InvalidResponseError);
+      }
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::encryptedReadMemory(int pageNum, SecretNum secretNum,
+                                        EncryptedPage & page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  vector<uint_least8_t> buffer;
+  buffer.push_back((secretNum << 6) | pageNum);
+  error_code result =
+      writeCommand(EncryptedReadMemory, &buffer[0], buffer.size());
+  if (!result) {
+    sleep(readMemoryTimeMs + sha256ComputationTimeMs);
+    result = readResponse(buffer);
+    if (!result) {
+      if (buffer.size() == (1 + page.challenge.size() + page.data.size())) {
+        result = convertResultByte(buffer[0]);
+        vector<uint_least8_t>::const_iterator begin = buffer.begin() + 1;
+        vector<uint_least8_t>::const_iterator end =
+            begin + page.challenge.size();
+        copy(begin, end, page.challenge.begin());
+        begin = end;
+        end = begin + page.data.size();
+        copy(begin, end, page.data.begin());
+      } else {
+        result = make_error_code(InvalidResponseError);
+      }
+    }
+  }
+  return result;
+}
+
+error_code
+DS28C36::computeAndReadPageAuthentication(int pageNum, AuthType authType,
+                                          vector<uint_least8_t> & data) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  data.clear();
+  data.push_back((authType << 5) | pageNum);
+  error_code result =
+      writeCommand(ComputeAndReadPathAuthentication, &data[0], data.size());
+  if (!result) {
+    sleep(readMemoryTimeMs + ((authType < EcdsaWithKeyA)
+                                  ? sha256ComputationTimeMs
+                                  : generateEcdsaSignatureTimeMs));
+    result = readResponse(data);
+    if (!result) {
+      if (data.size() > 1) {
+        result = convertResultByte(data[0]);
+        data.erase(data.begin());
+      } else {
+        result = make_error_code(InvalidResponseError);
+      }
+    }
+  }
+  return result;
+}
+
+error_code
+DS28C36::computeAndReadEcdsaPageAuthentication(int pageNum, KeyNum keyNum,
+                                               Signature & signature) {
+  AuthType authType;
+  switch (keyNum) {
+  case KeyNumA:
+    authType = EcdsaWithKeyA;
+    break;
+  case KeyNumB:
+    authType = EcdsaWithKeyB;
+    break;
+  case KeyNumC:
+    authType = EcdsaWithKeyC;
+    break;
+  default:
+    return make_error_code(InvalidParameterError);
+  }
+  vector<uint_least8_t> data;
+  error_code result = computeAndReadPageAuthentication(pageNum, authType, data);
+  if (!result) {
+    vector<uint_least8_t>::const_iterator begin = data.begin();
+    vector<uint_least8_t>::const_iterator end = begin + signature.s.size();
+    copy(begin, end, signature.s.begin());
+    begin = end;
+    end = begin + signature.r.size();
+    copy(begin, end, signature.r.begin());
+  }
+  return result;
+}
+
+error_code DS28C36::computeAndReadHmacPageAuthentication(int pageNum,
+                                                         SecretNum secretNum,
+                                                         Sha256::Hash & hmac) {
+  AuthType authType;
+  switch (secretNum) {
+  case SecretNumA:
+    authType = HmacWithSecretA;
+    break;
+  case SecretNumB:
+    authType = HmacWithSecretB;
+    break;
+  case SecretNumS:
+    authType = HmacWithSecretS;
+    break;
+  default:
+    return make_error_code(InvalidParameterError);
+  }
+  vector<uint_least8_t> data;
+  error_code result = computeAndReadPageAuthentication(pageNum, authType, data);
+  if (!result) {
+    copy(data.begin(), data.end(), hmac.begin());
+  }
+  return result;
+}
+
+error_code DS28C36::authenticatedSha2WriteMemory(int pageNum,
+                                                 SecretNum secretNum,
+                                                 const Page & page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  vector<uint_least8_t> buffer;
+  buffer.reserve(1 + page.size());
+  buffer.push_back((secretNum << 6) | pageNum);
+  buffer.insert(buffer.end(), page.begin(), page.end());
+  error_code result =
+      writeCommand(AuthenticatedSha2WriteMemory, &buffer[0], buffer.size());
+  if (!result) {
+    sleep(writeMemoryTimeMs + (2 * sha256ComputationTimeMs));
+    result = readResponse(buffer);
+    if (buffer.size() == 1) {
+      result = convertResultByte(buffer[0]);
+    } else {
+      result = make_error_code(InvalidResponseError);
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::computeAndLockSha2Secret(int pageNum, SecretNum msecretNum,
+                                             SecretNum dsecretNum,
+                                             bool writeProtectEnable) {
+  // User pages only
+  if (pageNum < UserData0 || pageNum > UserData15) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  vector<uint_least8_t> buffer;
+  buffer.push_back((dsecretNum << 6) | (msecretNum << 4) | pageNum);
+  buffer.push_back(writeProtectEnable ? 0x80 : 0x00);
+  error_code result =
+      writeCommand(ComputeAndLockSha2Secret, &buffer[0], buffer.size());
+  if (!result) {
+    sleep(sha256ComputationTimeMs +
+          ((writeProtectEnable ? 2 : 1) * writeMemoryTimeMs));
+    result = readResponse(buffer);
+    if (buffer.size() == 1) {
+      result = convertResultByte(buffer[0]);
+    } else {
+      result = make_error_code(InvalidResponseError);
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::generateEcc256KeyPair(KeyNum keyNum,
+                                          bool writeProtectEnable) {
+  if (keyNum == KeyNumS) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  vector<uint_least8_t> buffer;
+  uint_least8_t parameter = keyNum;
+  if (writeProtectEnable) {
+    parameter |= 0x80;
+  }
+  buffer.push_back(parameter);
+  error_code result =
+      writeCommand(GenerateEcc256KeyPair, &buffer[0], buffer.size());
+  if (!result) {
+    sleep(generateEccKeyPairTimeMs);
+    result = readResponse(buffer);
+    if (!result) {
+      if (buffer.size() == 1) {
+        result = convertResultByte(buffer[0]);
+      } else {
+        result = make_error_code(InvalidResponseError);
+      }
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::computeMultiblockHash(bool firstBlock, bool lastBlock,
+                                          const uint_least8_t * data,
+                                          size_t dataSize) {
+  uint_least8_t parameter = 0;
+  if (firstBlock) {
+    parameter |= 0x40;
+  }
+  if (lastBlock) {
+    parameter |= 0x80;
+  }
+  vector<uint_least8_t> buffer;
+  buffer.reserve(1 + dataSize);
+  buffer.push_back(parameter);
+  buffer.insert(buffer.end(), data, data + dataSize);
+  error_code result =
+      writeCommand(ComputeMultiblockHash, &buffer[0], buffer.size());
+  if (!result) {
+    sleep(sha256ComputationTimeMs);
+    result = readResponse(buffer);
+    if (!result) {
+      if (buffer.size() == 1) {
+        result = convertResultByte(buffer[0]);
+      } else {
+        result = make_error_code(InvalidResponseError);
+      }
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::verifyEcdsaSignature(KeyNum keyNum, HashType hashType,
+                                         const Signature & signature,
+                                         PioState pioa, PioState piob) {
+  uint_least8_t parameter = keyNum | (hashType << 2);
+  if (pioa != Unchanged) {
+    parameter |= 0x20;
+  }
+  if (pioa == Conducting) {
+    parameter |= 0x10;
+  }
+  if (piob != Unchanged) {
+    parameter |= 0x80;
+  }
+  if (piob == Conducting) {
+    parameter |= 0x40;
+  }
+  vector<uint_least8_t> buffer;
+  buffer.reserve(1 + signature.r.size() + signature.s.size());
+  buffer.push_back(parameter);
+  buffer.insert(buffer.end(), signature.r.begin(), signature.r.end());
+  buffer.insert(buffer.end(), signature.s.begin(), signature.s.end());
+  error_code result =
+      writeCommand(VerifyEcdsaSignature, &buffer[0], buffer.size());
+  if (!result) {
+    sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs +
+          ((hashType == DataInBuffer) ? sha256ComputationTimeMs : 0));
+    result = readResponse(buffer);
+    if (!result) {
+      if (buffer.size() == 1) {
+        result = convertResultByte(buffer[0]);
+      } else {
+        result = make_error_code(InvalidResponseError);
+      }
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::authenticateEcdsaPublicKey(bool authWrites, bool ecdh,
+                                               KeyNum keyNum, int csOffset,
+                                               const Signature & signature) {
+  if (((keyNum != KeyNumA) && (keyNum != KeyNumB)) || (csOffset < 0) ||
+      (csOffset > 31)) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t parameter = (csOffset << 3) | (keyNum << 2);
+  if (ecdh) {
+    parameter |= 0x02;
+  }
+  if (authWrites) {
+    parameter |= 0x01;
+  }
+  vector<uint_least8_t> buffer;
+  buffer.reserve(1 + signature.r.size() + signature.s.size());
+  buffer.push_back(parameter);
+  buffer.insert(buffer.end(), signature.r.begin(), signature.r.end());
+  buffer.insert(buffer.end(), signature.s.begin(), signature.s.end());
+  error_code result =
+      writeCommand(AuthenticateEcdsaPublicKey, &buffer[0], buffer.size());
+  if (!result) {
+    sleep((ecdh ? 2 : 1) * verifyEsdsaSignatureOrComputeEcdhTimeMs);
+    result = readResponse(buffer);
+    if (!result) {
+      if (buffer.size() == 1) {
+        result = convertResultByte(buffer[0]);
+      } else {
+        result = make_error_code(InvalidResponseError);
+      }
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::authenticatedEcdsaWriteMemory(int pageNum,
+                                                  const Page & page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  vector<uint_least8_t> buffer;
+  buffer.reserve(1 + page.size());
+  buffer.push_back(pageNum);
+  buffer.insert(buffer.end(), page.begin(), page.end());
+  error_code result =
+      writeCommand(AuthenticatedEcdsaWriteMemory, &buffer[0], buffer.size());
+  if (!result) {
+    sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs + writeMemoryTimeMs +
+          sha256ComputationTimeMs);
+    result = readResponse(buffer);
+    if (!result) {
+      if (buffer.size() == 1) {
+        result = convertResultByte(buffer[0]);
+      } else {
+        result = make_error_code(InvalidResponseError);
+      }
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::writeCommand(uint_least8_t command,
+                                 const uint_least8_t * parameters,
+                                 size_t parametersSize) {
+  error_code result = master->start(address_);
+  if (result) {
+    master->stop();
+    return result;
+  }
+  result = master->writeByte(command);
+  if (result) {
+    master->stop();
+    return result;
+  }
+  if (parameters) {
+    result = master->writeByte(static_cast<uint_least8_t>(parametersSize));
+    if (result) {
+      master->stop();
+      return result;
+    }
+    result = master->writeBlock(parameters, parametersSize);
+    if (result) {
+      master->stop();
+      return result;
+    }
+  }
+  result = master->stop();
+  return result;
+}
+
+error_code DS28C36::readResponse(vector<uint_least8_t> & response) {
+  error_code result = master->start(address_ | 1);
+  if (result) {
+    master->stop();
+    return result;
+  }
+  uint_least8_t length;
+  result = master->readByte(I2CMaster::Ack, length);
+  if (result) {
+    master->stop();
+    return result;
+  }
+  response.resize(length);
+  result = master->readBlock(I2CMaster::Nack, &response[0], response.size());
+  if (result) {
+    master->stop();
+    return result;
+  }
+  result = master->stop();
+  return result;
+}
+
+DS28C36::PageAuthenticationData
+DS28C36::createPageAuthenticationData(const RomId & romId, const Page & page,
+                                      const Page & challenge, int pageNum,
+                                      const ManId & manId) {
+  PageAuthenticationData data;
+  PageAuthenticationData::iterator dataIt = data.begin();
+  dataIt = copy(romId.begin(), romId.end(), dataIt);
+  dataIt = copy(page.begin(), page.end(), dataIt);
+  dataIt = copy(challenge.begin(), challenge.end(), dataIt);
+  *dataIt = static_cast<uint_least8_t>(pageNum);
+  ++dataIt;
+  copy(manId.begin(), manId.end(), dataIt);
+  return data;
+}
+
+const error_category & DS28C36::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "DS28C36"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case ProtectionError:
+        return "Protection Error";
+
+      case InvalidParameterError:
+        return "Invalid Parameter Error";
+
+      case InvalidSequenceError:
+        return "Invalid Sequence Error";
+
+      case InvalidEcdsaInputOrResultError:
+        return "Invalid ECDSA Input or Result Error";
+
+      case AuthenticationError:
+        return "Authentication Error";
+
+      case InvalidResponseError:
+        return "Invalid Response Error";
+
+      default:
+        return defaultErrorMessage(condition);
+      }
+    }
+  } instance;
+  return instance;
+}
+
+error_code readRomIdAndManId(DS28C36 & ds28c36, RomId * romId, ManId * manId) {
+  DS28C36::Page page;
+  const error_code result = ds28c36.readMemory(DS28C36::RomOptions, page);
+  if (!result) {
+    DS28C36::Page::const_iterator pageIt = page.begin() + 22;
+    if (manId) {
+      copy(pageIt, pageIt + ManId::size(), manId->begin());
+    }
+    pageIt += ManId::size();
+    if (romId) {
+      copy(pageIt, pageIt + RomId::size(), romId->begin());
+    }
+  }
+  return result;
+}
+
+error_code readRng(DS28C36 & ds28c36, uint_least8_t * data, size_t dataSize) {
+  error_code result;
+  vector<uint_least8_t> buffer;
+  while (dataSize > 0) {
+    result = ds28c36.readRng(static_cast<int>(std::min<size_t>(dataSize, 64)),
+                             buffer);
+    if (result) {
+      break;
+    }
+    copy(buffer.begin(), buffer.end(), data);
+    data += buffer.size();
+    dataSize -= buffer.size();
+  }
+  return result;
+}
+
+error_code computeMultiblockHash(DS28C36 & ds28c36, const uint_least8_t * data,
+                                 const size_t dataSize) {
+  error_code result;
+  size_t remainingSize = dataSize;
+  while ((remainingSize > 0) && !result) {
+    const size_t chunkSize = std::min<size_t>(remainingSize, 64);
+    result = ds28c36.computeMultiblockHash(
+        remainingSize == dataSize, remainingSize == chunkSize, data, chunkSize);
+    data += chunkSize;
+    remainingSize -= chunkSize;
+  }
+  return result;
+}
+
+error_code verifyEcdsaSignature(DS28C36 & ds28c36, DS28C36::KeyNum publicKey,
+                                const uint_least8_t * data, size_t dataSize,
+                                const Signature & signature,
+                                DS28C36::PioState pioa,
+                                DS28C36::PioState piob) {
+  error_code result = computeMultiblockHash(ds28c36, data, dataSize);
+  if (!result) {
+    result = ds28c36.verifyEcdsaSignature(publicKey, DS28C36::THASH, signature,
+                                          pioa, piob);
+  }
+  return result;
+}
+
+error_code verifyEcdsaSignature(DS28C36 & ds28c36, const PublicKey & publicKey,
+                                const uint_least8_t * data, size_t dataSize,
+                                const Signature & signature,
+                                DS28C36::PioState pioa,
+                                DS28C36::PioState piob) {
+  error_code result = ds28c36.writeMemory(DS28C36::PublicKeySX, publicKey.x);
+  if (!result) {
+    result = ds28c36.writeMemory(DS28C36::PublicKeySY, publicKey.y);
+  }
+  if (!result) {
+    result = verifyEcdsaSignature(ds28c36, DS28C36::KeyNumS, data, dataSize,
+                                  signature, pioa, piob);
+  }
+  return result;
+}
+
+// DS2476 additional commands.
+enum DS2476_Command {
+  GenerateEcdsaSignature = 0x1E,
+  ComputeSha2UniqueSecret = 0x55,
+  ComputeSha2Hmac = 0x2D
+};
+
+error_code DS2476::generateEcdsaSignature(KeyNum keyNum,
+                                          Ecc256::Signature & signature) {
+  if (keyNum == KeyNumS) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  vector<uint_least8_t> buffer;
+  buffer.push_back(keyNum);
+  error_code result =
+      writeCommand(GenerateEcdsaSignature, &buffer[0], buffer.size());
+  if (!result) {
+    sleep(generateEcdsaSignatureTimeMs);
+    result = readResponse(buffer);
+    if (!result) {
+      if (buffer.size() == (1 + signature.r.size() + signature.s.size())) {
+        result = convertResultByte(buffer[0]);
+        vector<uint_least8_t>::const_iterator begin = buffer.begin() + 1;
+        vector<uint_least8_t>::const_iterator end = begin + signature.s.size();
+        copy(begin, end, signature.s.begin());
+        begin = end;
+        end = begin + signature.r.size();
+        copy(begin, end, signature.r.begin());
+      } else {
+        result = make_error_code(InvalidResponseError);
+      }
+    }
+  }
+  return result;
+}
+
+error_code DS2476::computeSha2UniqueSecret(SecretNum msecretNum) {
+  vector<uint_least8_t> buffer;
+  buffer.push_back(msecretNum << 4);
+  error_code result =
+      writeCommand(ComputeSha2UniqueSecret, &buffer[0], buffer.size());
+  if (!result) {
+    sleep(sha256ComputationTimeMs);
+    result = readResponse(buffer);
+    if (!result) {
+      if (buffer.size() == 1) {
+        convertResultByte(buffer[0]);
+      } else {
+        result = make_error_code(InvalidResponseError);
+      }
+    }
+  }
+  return result;
+}
+
+error_code DS2476::computeSha2Hmac(Sha256::Hash & hmac) {
+  error_code result = writeCommand(ComputeSha2Hmac, NULL, 0);
+  if (!result) {
+    sleep(sha256ComputationTimeMs);
+    vector<uint_least8_t> buffer;
+    result = readResponse(buffer);
+    if (!result) {
+      if (buffer.size() == (1 + hmac.size())) {
+        result = convertResultByte(buffer[0]);
+        copy(buffer.begin() + 1, buffer.end(), hmac.begin());
+      } else {
+        result = make_error_code(InvalidResponseError);
+      }
+    }
+  }
+  return result;
+}
+
+error_code enableCoprocessor(DS2476 & ds2476) {
+  DS2476::Page gpioControl;
+  error_code result = ds2476.readMemory(DS2476::GpioControl, gpioControl);
+  if (!result && gpioControl[0] != 0xAA) {
+    gpioControl[0] = 0xAA;
+    result = ds2476.writeMemory(DS2476::GpioControl, gpioControl);
+  }
+  return result;
+}
+
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS28C36_DS2476.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,407 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_DS28C36_DS2476
+#define MaximInterface_DS28C36_DS2476
+
+#include <vector>
+#include <MaximInterface/Links/I2CMaster.hpp>
+#include <MaximInterface/Links/Sleep.hpp>
+#include <MaximInterface/Utilities/array.hpp>
+#include <MaximInterface/Utilities/Ecc256.hpp>
+#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/RomId.hpp>
+#include <MaximInterface/Utilities/ManId.hpp>
+#include <MaximInterface/Utilities/Sha256.hpp>
+#include <MaximInterface/Utilities/system_error.hpp>
+#include <MaximInterface/Utilities/FlagSet.hpp>
+
+namespace MaximInterface {
+
+/// Interface to the DS28C36 authenticator.
+class DS28C36 {
+public:
+  /// Device command results.
+  enum ErrorValue {
+    ProtectionError = 0x55,
+    InvalidParameterError = 0x77,
+    InvalidSequenceError = 0x33,
+    InvalidEcdsaInputOrResultError = 0x22,
+    AuthenticationError = 0x100,
+    InvalidResponseError = 0x101 ///< Response does not match expected format.
+  };
+
+  /// Device memory pages.
+  enum PageNum {
+    UserData0 = 0,
+    UserData1,
+    UserData2,
+    UserData3,
+    UserData4,
+    UserData5,
+    UserData6,
+    UserData7,
+    UserData8,
+    UserData9,
+    UserData10,
+    UserData11,
+    UserData12,
+    UserData13,
+    UserData14,
+    UserData15,
+    PublicKeyAX,
+    PublicKeyAY,
+    PublicKeyBX,
+    PublicKeyBY,
+    PublicKeyCX,
+    PublicKeyCY,
+    PrivateKeyA,
+    PrivateKeyB,
+    PrivateKeyC,
+    SecretA,
+    SecretB,
+    DecrementCounter,
+    RomOptions,
+    GpioControl,
+    PublicKeySX,
+    PublicKeySY
+  };
+
+  /// Available keys for ECDSA operations.
+  enum KeyNum { KeyNumA = 0, KeyNumB = 1, KeyNumC = 2, KeyNumS = 3 };
+
+  /// Available secrets for HMAC operations.
+  enum SecretNum { SecretNumA = 0, SecretNumB = 1, SecretNumS = 2 };
+
+  /// Data hash type when verifying an ECDSA signature.
+  enum HashType {
+    HashInBuffer = 0, ///< Hash is loaded in the buffer.
+    DataInBuffer = 1, ///< Compute hash from data loaded in the buffer.
+    THASH = 2         ///< Use THASH from Compute Multiblock Hash command.
+  };
+
+  /// Available PIO states when verifying an ECDSA signature.
+  enum PioState { Unchanged, Conducting, HighImpedance };
+
+  /// Holds a device memory page.
+  typedef array<uint_least8_t, 32> Page;
+
+  /// Holds page authentication input data.
+  typedef array<uint_least8_t, 75> PageAuthenticationData;
+
+  /// Page protection types.
+  enum PageProtectionType {
+    RP = 0x01,   ///< Read protection.
+    WP = 0x02,   ///< Write protection.
+    EM = 0x04,   ///< EPROM emulation mode.
+    APH = 0x08,  ///< Authentication write protection HMAC.
+    EPH = 0x10,  ///< Encryption and authenticated write protection HMAC.
+    AUTH = 0x20, ///< Public Key C is set to authority public key.
+    ECH = 0x40,  ///< Encrypted read and write using shared key from ECDH.
+    ECW = 0x80   ///< Authentication write protection ECDSA.
+  };
+  typedef FlagSet<PageProtectionType, 8> PageProtection;
+
+  /// Holds an encrypted device memory page.
+  struct EncryptedPage {
+    array<uint_least8_t, 8> challenge;
+    Page data;
+  };
+
+  /// Number of memory pages on the device.
+  static const int memoryPages = 32;
+
+  DS28C36(const Sleep & sleep, I2CMaster & master, uint_least8_t address = 0x36)
+      : sleep_(&sleep), master(&master), address_(address & 0xFE) {}
+
+  void setSleep(const Sleep & sleep) { this->sleep_ = &sleep; }
+  void setMaster(I2CMaster & master) { this->master = &master; }
+  uint_least8_t address() const { return address_; }
+  void setAddress(uint_least8_t address) { this->address_ = (address & 0xFE); }
+
+  /// Write memory with no protection.
+  /// @param pageNum Number of page to write.
+  /// @param page Data to write.
+  MaximInterface_EXPORT error_code writeMemory(int pageNum, const Page & page);
+
+  /// Read memory with no protection.
+  /// @param pageNum Number of page to read.
+  /// @param[out] page Data that was read.
+  MaximInterface_EXPORT error_code readMemory(int pageNum, Page & page);
+
+  /// Write the temporary buffer.
+  /// @param data Data to write.
+  /// @param dataSize Size of data to write.
+  MaximInterface_EXPORT error_code writeBuffer(const uint_least8_t * data,
+                                               size_t dataSize);
+
+  /// Read the temporary buffer.
+  /// @param[out] data Data that was read.
+  MaximInterface_EXPORT error_code
+  readBuffer(std::vector<uint_least8_t> & data);
+
+  /// Read the protection settings of a page.
+  /// @param pageNum Number of page to read.
+  /// @param[out] protection Protection that was read.
+  MaximInterface_EXPORT error_code
+  readPageProtection(int pageNum, PageProtection & protection);
+
+  /// Set the protection settings of a page.
+  /// @param pageNum Number of page to write.
+  /// @param protection Protection to write.
+  MaximInterface_EXPORT error_code
+  setPageProtection(int pageNum, const PageProtection & protection);
+
+  /// Decrement the decrement-only counter.
+  MaximInterface_EXPORT error_code decrementCounter();
+
+  /// Read a block of random data from the RNG.
+  /// @param numBytes Number of bytes to read from 1 to 64.
+  /// @param[out] data Random data from RNG.
+  MaximInterface_EXPORT error_code readRng(int numBytes,
+                                           std::vector<uint_least8_t> & data);
+
+  /// Read memory with encryption.
+  /// @param pageNum Number of page to read from.
+  /// @param secretNum Secret to use for encryption.
+  /// @param[out] page Data that was read.
+  MaximInterface_EXPORT error_code encryptedReadMemory(int pageNum,
+                                                       SecretNum secretNum,
+                                                       EncryptedPage & page);
+
+  /// Compute and read page authentication with ECDSA.
+  /// @param pageNum Number of page to authenticate.
+  /// @param keyNum Private key to use for authentication.
+  /// Key S cannot be used with this command.
+  /// @param[out] signature Computed page signature.
+  MaximInterface_EXPORT error_code computeAndReadEcdsaPageAuthentication(
+      int pageNum, KeyNum keyNum, Ecc256::Signature & signature);
+
+  /// Compute and read page authentication with HMAC.
+  /// @param pageNum Number of page to authenticate.
+  /// @param secretNum Secret to use for authentication.
+  /// @param[out] hmac Computed page HMAC.
+  MaximInterface_EXPORT error_code computeAndReadHmacPageAuthentication(
+      int pageNum, SecretNum secretNum, Sha256::Hash & hmac);
+
+  /// Write with SHA2 authentication.
+  /// @param pageNum Number of page to write.
+  /// @param secretNum Secret to use for authentication.
+  /// @param page Data to write.
+  MaximInterface_EXPORT error_code authenticatedSha2WriteMemory(
+      int pageNum, SecretNum secretNum, const Page & page);
+
+  /// Compute SHA2 secret and optionally lock.
+  /// @param pageNum Number of page to use in computation.
+  /// @param msecretNum Master secret to use in computation.
+  /// @param dsecretNum Destination secret to receive the computation result.
+  /// @param writeProtectEnable
+  /// True to lock the destination secret against further writes.
+  MaximInterface_EXPORT error_code
+  computeAndLockSha2Secret(int pageNum, SecretNum msecretNum,
+                           SecretNum dsecretNum, bool writeProtectEnable);
+
+  /// Generate a new ECDSA key pair.
+  /// @param keyNum Key to generate. Key S cannot be used with this command.
+  /// @param writeProtectEnable True to lock the key against further writes.
+  MaximInterface_EXPORT error_code
+  generateEcc256KeyPair(KeyNum keyNum, bool writeProtectEnable);
+
+  /// Compute a hash over multiple blocks.
+  /// @param firstBlock True if this is the first block being hashed.
+  /// @param lastBlock True if this is the last block being hashed.
+  /// @param data Data block to hash.
+  /// @param dataSize Size of data to hash.
+  /// Should be 64 bytes unless this is the last block.
+  MaximInterface_EXPORT error_code
+  computeMultiblockHash(bool firstBlock, bool lastBlock,
+                        const uint_least8_t * data, size_t dataSize);
+
+  /// Verify ECDSA signature.
+  /// @param keyNum Public key to use for verification.
+  /// @param hashType Source of the data hash input.
+  /// @param signature Signature to verify.
+  /// @param pioa New state of PIOA if verification successful.
+  /// @param piob New state of PIOB if verification successful.
+  MaximInterface_EXPORT error_code verifyEcdsaSignature(
+      KeyNum keyNum, HashType hashType, const Ecc256::Signature & signature,
+      PioState pioa = Unchanged, PioState piob = Unchanged);
+
+  /// Authenticate a public key for authenticated writes or encrypted reads with ECDH.
+  /// @param authWrites True to select authentication for writes.
+  /// @param ecdh True to select ECDH key exchange.
+  /// @param keyNum Private key to use for ECDH key exchange.
+  /// Key A or B can be selected.
+  /// @param csOffset Certificate customization field ending offset in buffer.
+  /// @param signature Signature to use for authentication of public key S.
+  MaximInterface_EXPORT error_code
+  authenticateEcdsaPublicKey(bool authWrites, bool ecdh, KeyNum keyNum,
+                             int csOffset, const Ecc256::Signature & signature);
+
+  /// Write with ECDSA authentication.
+  /// @param pageNum Number of page to write.
+  /// @param page Data to write.
+  MaximInterface_EXPORT error_code
+  authenticatedEcdsaWriteMemory(int pageNum, const Page & page);
+
+  /// Create data used by the Compute and Read Page Authentication command to
+  /// generate a signature.
+  MaximInterface_EXPORT static PageAuthenticationData
+  createPageAuthenticationData(const RomId & romId, const Page & page,
+                               const Page & challenge, int pageNum,
+                               const ManId & manId);
+
+  MaximInterface_EXPORT static const error_category & errorCategory();
+
+protected:
+  // Timing constants.
+  static const int generateEcdsaSignatureTimeMs = 50;
+  static const int generateEccKeyPairTimeMs = 100;
+  static const int verifyEsdsaSignatureOrComputeEcdhTimeMs = 150;
+  static const int sha256ComputationTimeMs = 3;
+  static const int readMemoryTimeMs = /*1*/ 2;
+  static const int writeMemoryTimeMs = 15;
+
+  error_code writeCommand(uint_least8_t command,
+                          const uint_least8_t * parameters,
+                          size_t parametersSize);
+  error_code readResponse(std::vector<uint_least8_t> & response);
+
+  void sleep(int ms) const { (*sleep_)(ms); }
+
+private:
+  enum AuthType {
+    HmacWithSecretA = 0,
+    HmacWithSecretB = 1,
+    HmacWithSecretS = 2,
+    EcdsaWithKeyA = 3,
+    EcdsaWithKeyB = 4,
+    EcdsaWithKeyC = 5
+  };
+
+  const Sleep * sleep_;
+  I2CMaster * master;
+  uint_least8_t address_;
+
+  /// Compute any type of authentication on page.
+  /// @param pageNum Number of page to authenticate.
+  /// @param authType Method to use to compute authentication.
+  /// @param[out] data Raw computed page authentication.
+  error_code
+  computeAndReadPageAuthentication(int pageNum, AuthType authType,
+                                   std::vector<uint_least8_t> & data);
+};
+
+/// Read the device ROM ID and MAN ID using the Read Memory command on the
+/// ROM Options page.
+/// @param[out] romId
+/// Read ROM ID valid when operation is successful. May be set to NULL.
+/// @param[out] manId
+/// Read MAN ID valid when operation is successful. May be set to NULL.
+MaximInterface_EXPORT error_code readRomIdAndManId(DS28C36 & ds28c36,
+                                                   RomId * romId,
+                                                   ManId * manId);
+
+/// Read arbitrary length random data with successive Read RNG commands.
+/// @param[out] data Buffer to receive random data.
+/// @param dataSize Size of data buffer.
+MaximInterface_EXPORT error_code readRng(DS28C36 & ds28c36,
+                                         uint_least8_t * data, size_t dataSize);
+
+/// Hash arbitrary length data with successive Compute Multiblock Hash commands.
+/// @param data Data to hash.
+/// @param dataSize Size of data to hash.
+MaximInterface_EXPORT error_code computeMultiblockHash(
+    DS28C36 & ds28c36, const uint_least8_t * data, const size_t dataSize);
+
+/// Verify ECDSA signature.
+/// @param publicKey Public key to use for verification.
+/// @param data Data to verify.
+/// @param dataSize Size of data to verify.
+/// @param signature Signature to verify.
+/// @param pioa New state of PIOA if verification successful.
+/// @param piob New state of PIOB if verification successful.
+MaximInterface_EXPORT error_code verifyEcdsaSignature(
+    DS28C36 & ds28c36, DS28C36::KeyNum publicKey, const uint_least8_t * data,
+    size_t dataSize, const Ecc256::Signature & signature,
+    DS28C36::PioState pioa = DS28C36::Unchanged,
+    DS28C36::PioState piob = DS28C36::Unchanged);
+
+/// Verify ECDSA signature.
+/// @param publicKey
+/// Public key to use for verification which is loaded into Public Key S.
+/// @param data Data to verify.
+/// @param dataSize Size of data to verify.
+/// @param signature Signature to verify.
+/// @param pioa New state of PIOA if verification successful.
+/// @param piob New state of PIOB if verification successful.
+MaximInterface_EXPORT error_code
+verifyEcdsaSignature(DS28C36 & ds28c36, const Ecc256::PublicKey & publicKey,
+                     const uint_least8_t * data, size_t dataSize,
+                     const Ecc256::Signature & signature,
+                     DS28C36::PioState pioa = DS28C36::Unchanged,
+                     DS28C36::PioState piob = DS28C36::Unchanged);
+
+inline error_code make_error_code(DS28C36::ErrorValue e) {
+  return error_code(e, DS28C36::errorCategory());
+}
+
+/// Interface to the DS2476 coprocessor.
+class DS2476 : public DS28C36 {
+public:
+  DS2476(const Sleep & sleep, I2CMaster & master, uint_least8_t address = 0x76)
+      : DS28C36(sleep, master, address) {}
+
+  /// Generate ECDSA signature.
+  /// @param keyNum Private key to use to create signature.
+  /// Key S cannot be used with this command.
+  /// @param[out] signature Computed signature.
+  MaximInterface_EXPORT error_code
+  generateEcdsaSignature(KeyNum keyNum, Ecc256::Signature & signature);
+
+  /// Compute unique SHA2 secret.
+  /// @param msecretNum Master secret to use in computation.
+  MaximInterface_EXPORT error_code
+  computeSha2UniqueSecret(SecretNum msecretNum);
+
+  /// Compute SHA2 HMAC.
+  /// @param[out] hmac Computed HMAC.
+  MaximInterface_EXPORT error_code computeSha2Hmac(Sha256::Hash & hmac);
+};
+
+/// Enable coprocessor functionality on the DS2476 by writing to the
+/// ROM Options page.
+MaximInterface_EXPORT error_code enableCoprocessor(DS2476 & ds2476);
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS28E15_22_25.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,715 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <algorithm>
+#include "DS28E15_22_25.hpp"
+#include <MaximInterface/Utilities/crc.hpp>
+#include <MaximInterface/Utilities/Error.hpp>
+
+using std::copy;
+
+namespace MaximInterface {
+
+using namespace Sha256;
+
+static const int shaComputationDelayMs = 3;
+static const int eepromWriteDelayMs = 10;
+static inline int secretEepromWriteDelayMs(bool lowPower) {
+  return lowPower ? 200 : 100;
+}
+static const int ds28e22_25_pagesPerBlock = 2;
+
+static error_code
+writeDataWithCrc(OneWireMaster & master, const uint_least8_t * data,
+                 size_t dataLen,
+                 OneWireMaster::Level level = OneWireMaster::NormalLevel,
+                 uint_fast16_t crcStart = 0) {
+  error_code result = master.writeBlock(data, dataLen);
+  if (result) {
+    return result;
+  }
+  uint_least8_t response[2];
+  result = master.readByte(response[0]);
+  if (result) {
+    return result;
+  }
+  result = master.readByteSetLevel(response[1], level);
+  if (result) {
+    return result;
+  }
+  if (calculateCrc16(response, sizeof(response) / sizeof(response[0]),
+                     calculateCrc16(data, dataLen, crcStart)) != 0xB001) {
+    result = make_error_code(DS28E15_22_25::CrcError);
+  }
+  return result;
+}
+
+error_code
+DS28E15_22_25::writeCommandWithCrc(Command command, uint_least8_t parameter,
+                                   OneWireMaster::Level level) const {
+  error_code result = selectRom(*master);
+  if (!result) {
+    const uint_least8_t data[] = {static_cast<uint_least8_t>(command),
+                                  parameter};
+    result =
+        writeDataWithCrc(*master, data, sizeof(data) / sizeof(data[0]), level);
+  }
+  return result;
+}
+
+static error_code readDataWithCrc(OneWireMaster & master, uint_least8_t * data,
+                                  size_t dataLen) {
+  error_code result = master.readBlock(data, dataLen);
+  if (result) {
+    return result;
+  }
+  uint_least8_t response[2];
+  const size_t responseLen = sizeof(response) / sizeof(response[0]);
+  result = master.readBlock(response, responseLen);
+  if (result) {
+    return result;
+  }
+  if (calculateCrc16(response, responseLen, calculateCrc16(data, dataLen)) !=
+      0xB001) {
+    result = make_error_code(DS28E15_22_25::CrcError);
+  }
+  return result;
+}
+
+static error_code readCsByte(OneWireMaster & master) {
+  uint_least8_t response;
+  error_code result = master.readByte(response);
+  if (result) {
+    return result;
+  }
+  if (response != 0xAA) {
+    result = make_error_code(DS28E15_22_25::OperationFailure);
+  }
+  return result;
+}
+
+static error_code releaseSequence(OneWireMaster & master, const Sleep & sleep,
+                                  int delayTimeMs) {
+  error_code result = master.writeBytePower(0xAA);
+  if (result) {
+    return result;
+  }
+  sleep(delayTimeMs);
+  result = master.setLevel(OneWireMaster::NormalLevel);
+  if (result) {
+    return result;
+  }
+  return readCsByte(master);
+}
+
+DS28E15_22_25::BlockProtection::BlockProtection(bool readProtection,
+                                                bool writeProtection,
+                                                bool eepromEmulation,
+                                                bool authProtection,
+                                                int blockNum) {
+  setReadProtection(readProtection);
+  setWriteProtection(writeProtection);
+  setEepromEmulation(eepromEmulation);
+  setAuthProtection(authProtection);
+  setBlockNum(blockNum);
+}
+
+void DS28E15_22_25::BlockProtection::setBlockNum(int blockNum) {
+  status &= ~blockNumMask;
+  status |= (blockNum & blockNumMask);
+}
+
+bool DS28E15_22_25::BlockProtection::noProtection() const {
+  return !readProtection() && !writeProtection() && !eepromEmulation() &&
+         !authProtection();
+}
+
+void DS28E15_22_25::BlockProtection::setReadProtection(bool readProtection) {
+  if (readProtection) {
+    status |= readProtectionMask;
+  } else {
+    status &= ~readProtectionMask;
+  }
+}
+
+void DS28E15_22_25::BlockProtection::setWriteProtection(bool writeProtection) {
+  if (writeProtection) {
+    status |= writeProtectionMask;
+  } else {
+    status &= ~writeProtectionMask;
+  }
+}
+
+void DS28E15_22_25::BlockProtection::setEepromEmulation(bool eepromEmulation) {
+  if (eepromEmulation) {
+    status |= eepromEmulationMask;
+  } else {
+    status &= ~eepromEmulationMask;
+  }
+}
+
+void DS28E15_22_25::BlockProtection::setAuthProtection(bool authProtection) {
+  if (authProtection) {
+    status |= authProtectionMask;
+  } else {
+    status &= ~authProtectionMask;
+  }
+}
+
+error_code
+DS28E15_22_25::writeAuthBlockProtection(const BlockProtection & newProtection,
+                                        const Hash & mac) {
+  error_code result =
+      writeCommandWithCrc(AuthWriteBlockProtection, newProtection.statusByte(),
+                          OneWireMaster::StrongLevel);
+  if (result) {
+    return result;
+  }
+
+  (*sleep)(shaComputationDelayMs);
+  result = master->setLevel(OneWireMaster::NormalLevel);
+  if (result) {
+    return result;
+  }
+
+  result = writeDataWithCrc(*master, mac.data(), mac.size());
+  if (result) {
+    return result;
+  }
+
+  result = readCsByte(*master);
+  if (result) {
+    return result;
+  }
+
+  result = releaseSequence(*master, *sleep, eepromWriteDelayMs);
+  return result;
+}
+
+error_code
+DS28E15_22_25::writeBlockProtection(const BlockProtection & protection) {
+  error_code result =
+      writeCommandWithCrc(WriteBlockProtection, protection.statusByte());
+  if (result) {
+    return result;
+  }
+
+  result = releaseSequence(*master, *sleep, eepromWriteDelayMs);
+  return result;
+}
+
+error_code DS28E15_22_25::doReadBlockProtection(int blockNum,
+                                                BlockProtection & protection,
+                                                Variant variant) const {
+  uint_least8_t buffer = blockNum;
+  if (variant == DS28E22 || variant == DS28E25) {
+    buffer *= ds28e22_25_pagesPerBlock;
+  }
+  error_code result = writeCommandWithCrc(ReadStatus, buffer);
+  if (!result) {
+    result = master->readByte(buffer);
+    if (!result) {
+      protection.setStatusByte(buffer);
+    }
+  }
+  return result;
+}
+
+AuthMacData DS28E15_22_25::createAuthMacData(const Page & pageData, int pageNum,
+                                             const Scratchpad & challenge,
+                                             const RomId & romId,
+                                             const ManId & manId) {
+  AuthMacData authMacData;
+  AuthMacData::iterator authMacDataIt = authMacData.begin();
+  authMacDataIt = copy(pageData.begin(), pageData.end(), authMacDataIt);
+  authMacDataIt = copy(challenge.begin(), challenge.end(), authMacDataIt);
+  authMacDataIt = copy(romId.begin(), romId.end(), authMacDataIt);
+  *authMacDataIt = manId[1];
+  *(++authMacDataIt) = manId[0];
+  *(++authMacDataIt) = pageNum;
+  *(++authMacDataIt) = 0x00;
+  return authMacData;
+}
+
+AuthMacData DS28E15_22_25::createAnonAuthMacData(const Page & pageData,
+                                                 int pageNum,
+                                                 const Scratchpad & challenge,
+                                                 const ManId & manId) {
+  RomId romId;
+  romId.fill(0xFF);
+  return createAuthMacData(pageData, pageNum, challenge, romId, manId);
+}
+
+error_code DS28E15_22_25::computeReadPageMac(int page_num, bool anon,
+                                             Hash & mac) const {
+  error_code result =
+      writeCommandWithCrc(ComputePageMac, (anon ? 0xE0 : 0x00) | page_num,
+                          OneWireMaster::StrongLevel);
+  if (result) {
+    return result;
+  }
+
+  (*sleep)(shaComputationDelayMs * 2);
+  result = master->setLevel(OneWireMaster::NormalLevel);
+  if (result) {
+    return result;
+  }
+
+  result = readCsByte(*master);
+  if (result) {
+    return result;
+  }
+
+  result = readDataWithCrc(*master, mac.data(), mac.size());
+  return result;
+}
+
+error_code DS28E15_22_25::doComputeSecret(int page_num, bool lock,
+                                          bool lowPower) {
+  error_code result = writeCommandWithCrc(ComputeAndLockSecret,
+                                          lock ? (0xE0 | page_num) : page_num);
+  if (result) {
+    return result;
+  }
+
+  result = releaseSequence(*master, *sleep,
+                           shaComputationDelayMs * 2 +
+                               secretEepromWriteDelayMs(lowPower));
+  return result;
+}
+
+error_code DS28E15_22_25::doWriteScratchpad(const Scratchpad & data,
+                                            Variant variant) {
+  const uint_least8_t parameter =
+      (variant == DS28E22 || variant == DS28E25) ? 0x20 : 0x00;
+  error_code result = writeCommandWithCrc(ReadWriteScratchpad, parameter);
+  if (result) {
+    return result;
+  }
+
+  result = writeDataWithCrc(*master, data.data(), data.size());
+  return result;
+}
+
+error_code DS28E15_22_25::doReadScratchpad(Scratchpad & data,
+                                           Variant variant) const {
+  const uint_least8_t parameter =
+      (variant == DS28E22 || variant == DS28E25) ? 0x2F : 0x0F;
+  error_code result = writeCommandWithCrc(ReadWriteScratchpad, parameter);
+  if (result) {
+    return result;
+  }
+
+  result = readDataWithCrc(*master, data.data(), data.size());
+  return result;
+}
+
+error_code DS28E15_22_25::doLoadSecret(bool lock, bool lowPower) {
+  error_code result =
+      writeCommandWithCrc(LoadAndLockSecret, lock ? 0xE0 : 0x00);
+  if (result) {
+    return result;
+  }
+
+  result = releaseSequence(*master, *sleep, secretEepromWriteDelayMs(lowPower));
+  return result;
+}
+
+error_code DS28E15_22_25::readPage(int page, Page & rdbuf) const {
+  error_code result = writeCommandWithCrc(ReadMemory, page);
+  if (result) {
+    return result;
+  }
+
+  result = continueReadPage(rdbuf);
+  return result;
+}
+
+error_code DS28E15_22_25::continueReadPage(Page & rdbuf) const {
+  return readDataWithCrc(*master, rdbuf.data(), rdbuf.size());
+}
+
+error_code DS28E15_22_25::doWriteAuthSegment(const Segment & newData,
+                                             const Hash & mac, Variant variant,
+                                             bool continuing) {
+  // CRC gets calculated with CS byte when continuing on DS28E22 and DS28E25.
+  const uint_fast16_t crcStart =
+      ((variant == DS28E22 || variant == DS28E25) && continuing)
+          ? calculateCrc16(0xAA)
+          : 0;
+  error_code result = writeDataWithCrc(*master, newData.data(), newData.size(),
+                                       OneWireMaster::StrongLevel, crcStart);
+  if (result) {
+    return result;
+  }
+
+  (*sleep)(shaComputationDelayMs);
+  result = master->setLevel(OneWireMaster::NormalLevel);
+  if (result) {
+    return result;
+  }
+
+  result = writeDataWithCrc(*master, mac.data(), mac.size());
+  if (result) {
+    return result;
+  }
+
+  result = readCsByte(*master);
+  if (result) {
+    return result;
+  }
+
+  result = releaseSequence(*master, *sleep, eepromWriteDelayMs);
+  return result;
+}
+
+error_code DS28E15_22_25::doWriteAuthSegment(int pageNum, int segmentNum,
+                                             const Segment & newData,
+                                             const Hash & mac,
+                                             Variant variant) {
+  error_code result =
+      writeCommandWithCrc(AuthWriteMemory, (segmentNum << 5) | pageNum);
+  if (result) {
+    return result;
+  }
+
+  result = doWriteAuthSegment(newData, mac, variant, false);
+  return result;
+}
+
+error_code DS28E15_22_25::doContinueWriteAuthSegment(const Segment & newData,
+                                                     const Hash & mac,
+                                                     Variant variant) {
+  return doWriteAuthSegment(newData, mac, variant, true);
+}
+
+WriteMacData DS28E15_22_25::createSegmentWriteMacData(
+    int pageNum, int segmentNum, const Segment & newData,
+    const Segment & oldData, const RomId & romId, const ManId & manId) {
+  WriteMacData MT;
+
+  // insert ROM number
+  copy(romId.begin(), romId.end(), MT.begin());
+
+  MT[11] = segmentNum;
+  MT[10] = pageNum;
+  MT[9] = manId[0];
+  MT[8] = manId[1];
+
+  // insert old data
+  copy(oldData.begin(), oldData.end(), MT.begin() + 12);
+
+  // insert new data
+  copy(newData.begin(), newData.end(), MT.begin() + 16);
+
+  return MT;
+}
+
+WriteMacData DS28E15_22_25::createProtectionWriteMacData(
+    const BlockProtection & newProtection,
+    const BlockProtection & oldProtection, const RomId & romId,
+    const ManId & manId) {
+  WriteMacData MT;
+
+  // insert ROM number
+  copy(romId.begin(), romId.end(), MT.begin());
+
+  // instert block and page
+  MT[11] = 0;
+  MT[10] = newProtection.blockNum();
+
+  MT[9] = manId[0];
+  MT[8] = manId[1];
+
+  // old data
+  MT[12] = oldProtection.authProtection() ? 0x01 : 0x00;
+  MT[13] = oldProtection.eepromEmulation() ? 0x01 : 0x00;
+  MT[14] = oldProtection.writeProtection() ? 0x01 : 0x00;
+  MT[15] = oldProtection.readProtection() ? 0x01 : 0x00;
+  // new data
+  MT[16] = newProtection.authProtection() ? 0x01 : 0x00;
+  MT[17] = newProtection.eepromEmulation() ? 0x01 : 0x00;
+  MT[18] = newProtection.writeProtection() ? 0x01 : 0x00;
+  MT[19] = newProtection.readProtection() ? 0x01 : 0x00;
+
+  // compute the mac
+  return MT;
+}
+
+error_code DS28E15_22_25::readSegment(int page, int segment,
+                                      Segment & data) const {
+  error_code result = writeCommandWithCrc(ReadMemory, (segment << 5) | page);
+  if (result) {
+    return result;
+  }
+
+  result = continueReadSegment(data);
+  return result;
+}
+
+error_code DS28E15_22_25::continueReadSegment(Segment & data) const {
+  return master->readBlock(data.data(), data.size());
+}
+
+error_code DS28E15_22_25::writeSegment(int page, int block,
+                                       const Segment & data) {
+  error_code result = writeCommandWithCrc(WriteMemory, (block << 5) | page);
+  if (result) {
+    return result;
+  }
+
+  result = continueWriteSegment(data);
+  return result;
+}
+
+error_code DS28E15_22_25::continueWriteSegment(const Segment & data) {
+  error_code result = writeDataWithCrc(*master, data.data(), data.size());
+  if (result) {
+    return result;
+  }
+
+  result = releaseSequence(*master, *sleep, eepromWriteDelayMs);
+  return result;
+}
+
+SlaveSecretData
+DS28E15_22_25::createSlaveSecretData(const Page & bindingPage,
+                                     int bindingPageNum,
+                                     const Scratchpad & partialSecret,
+                                     const RomId & romId, const ManId & manId) {
+  SlaveSecretData slaveSecretData;
+  SlaveSecretData::iterator slaveSecretDataIt = slaveSecretData.begin();
+  slaveSecretDataIt =
+      copy(bindingPage.begin(), bindingPage.end(), slaveSecretDataIt);
+  slaveSecretDataIt =
+      copy(partialSecret.begin(), partialSecret.end(), slaveSecretDataIt);
+  slaveSecretDataIt = copy(romId.begin(), romId.end(), slaveSecretDataIt);
+  *slaveSecretDataIt = manId[1];
+  *(++slaveSecretDataIt) = manId[0];
+  *(++slaveSecretDataIt) = bindingPageNum;
+  *(++slaveSecretDataIt) = 0x00;
+  return slaveSecretData;
+}
+
+error_code DS28E15_22_25::doReadAllBlockProtection(BlockProtection * protection,
+                                                   const size_t protectionLen,
+                                                   Variant variant) const {
+  error_code result = writeCommandWithCrc(ReadStatus, 0);
+  if (!result) {
+    if (variant == DS28E22 || variant == DS28E25) {
+      // Need to read extra data on DS28E22 to get CRC16.
+      uint_least8_t buf[DS28E25::memoryPages];
+      result = readDataWithCrc(*master, buf, DS28E25::memoryPages);
+      if (!result) {
+        const int blocks = ((variant == DS28E22) ? DS28E22::memoryPages
+                                                 : DS28E25::memoryPages) /
+                           ds28e22_25_pagesPerBlock;
+        for (size_t i = 0;
+             i < std::min(protectionLen, static_cast<size_t>(blocks)); i++) {
+          protection[i].setStatusByte(
+              (buf[i * ds28e22_25_pagesPerBlock] & 0xF0) | // Upper nibble
+              ((buf[i * ds28e22_25_pagesPerBlock] & 0x0F) /
+               ds28e22_25_pagesPerBlock)); // Lower nibble
+        }
+      }
+    } else // DS28E15
+    {
+      uint_least8_t buf[DS28E15::protectionBlocks];
+      result = readDataWithCrc(*master, buf, DS28E15::protectionBlocks);
+      if (!result) {
+        for (size_t i = 0;
+             i < std::min(protectionLen,
+                          static_cast<size_t>(DS28E15::protectionBlocks));
+             i++) {
+          protection[i].setStatusByte(buf[i]);
+        }
+      }
+    }
+  }
+  return result;
+}
+
+const error_category & DS28E15_22_25::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "DS28E15_22_25"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case CrcError:
+        return "CRC Error";
+
+      case OperationFailure:
+        return "Operation Failure";
+
+      default:
+        return defaultErrorMessage(condition);
+      }
+    }
+  } instance;
+  return instance;
+}
+
+error_code DS28E15_22_25::loadSecret(bool lock) {
+  // Use worst-case low power timing if the device type is not known.
+  return doLoadSecret(lock, true);
+}
+
+error_code DS28E15_22_25::computeSecret(int pageNum, bool lock) {
+  // Use worst-case low power timing if the device type is not known.
+  return doComputeSecret(pageNum, lock, true);
+}
+
+error_code DS28E15_22_25::readPersonality(Personality & personality) const {
+  error_code result = writeCommandWithCrc(ReadStatus, 0xE0);
+  if (!result) {
+    array<uint_least8_t, 4> data;
+    result = readDataWithCrc(*master, data.data(), data.size());
+    if (!result) {
+      personality.PB1 = data[0];
+      personality.PB2 = data[1];
+      personality.manId[0] = data[2];
+      personality.manId[1] = data[3];
+    }
+  }
+  return result;
+}
+
+error_code DS28EL15::writeScratchpad(const Scratchpad & data) {
+  return doWriteScratchpad(data, DS28E15);
+}
+
+error_code DS28EL15::readScratchpad(Scratchpad & data) const {
+  return doReadScratchpad(data, DS28E15);
+}
+
+error_code DS28EL15::readBlockProtection(int blockNum,
+                                         BlockProtection & protection) const {
+  return doReadBlockProtection(blockNum, protection, DS28E15);
+}
+
+error_code DS28EL15::writeAuthSegment(int pageNum, int segmentNum,
+                                      const Segment & newData,
+                                      const Hash & mac) {
+  return doWriteAuthSegment(pageNum, segmentNum, newData, mac, DS28E15);
+}
+
+error_code DS28EL15::continueWriteAuthSegment(const Segment & newData,
+                                              const Hash & mac) {
+  return doContinueWriteAuthSegment(newData, mac, DS28E15);
+}
+
+error_code DS28EL15::readAllBlockProtection(
+    array<BlockProtection, protectionBlocks> & protection) const {
+  return doReadAllBlockProtection(protection.data(), protection.size(),
+                                  DS28E15);
+}
+
+error_code DS28E15::loadSecret(bool lock) { return doLoadSecret(lock, false); }
+
+error_code DS28E15::computeSecret(int pageNum, bool lock) {
+  return doComputeSecret(pageNum, lock, false);
+}
+
+error_code DS28EL22::writeScratchpad(const Scratchpad & data) {
+  return doWriteScratchpad(data, DS28E22);
+}
+
+error_code DS28EL22::readScratchpad(Scratchpad & data) const {
+  return doReadScratchpad(data, DS28E22);
+}
+
+error_code DS28EL22::readBlockProtection(int blockNum,
+                                         BlockProtection & protection) const {
+  return doReadBlockProtection(blockNum, protection, DS28E22);
+}
+
+error_code DS28EL22::writeAuthSegment(int pageNum, int segmentNum,
+                                      const Segment & newData,
+                                      const Hash & mac) {
+  return doWriteAuthSegment(pageNum, segmentNum, newData, mac, DS28E22);
+}
+
+error_code DS28EL22::continueWriteAuthSegment(const Segment & newData,
+                                              const Hash & mac) {
+  return doContinueWriteAuthSegment(newData, mac, DS28E22);
+}
+
+error_code DS28EL22::readAllBlockProtection(
+    array<BlockProtection, protectionBlocks> & protection) const {
+  return doReadAllBlockProtection(protection.data(), protection.size(),
+                                  DS28E22);
+}
+
+error_code DS28E22::loadSecret(bool lock) { return doLoadSecret(lock, false); }
+
+error_code DS28E22::computeSecret(int pageNum, bool lock) {
+  return doComputeSecret(pageNum, lock, false);
+}
+
+error_code DS28EL25::writeScratchpad(const Scratchpad & data) {
+  return doWriteScratchpad(data, DS28E25);
+}
+
+error_code DS28EL25::readScratchpad(Scratchpad & data) const {
+  return doReadScratchpad(data, DS28E25);
+}
+
+error_code DS28EL25::readBlockProtection(int blockNum,
+                                         BlockProtection & protection) const {
+  return doReadBlockProtection(blockNum, protection, DS28E25);
+}
+
+error_code DS28EL25::writeAuthSegment(int pageNum, int segmentNum,
+                                      const Segment & newData,
+                                      const Hash & mac) {
+  return doWriteAuthSegment(pageNum, segmentNum, newData, mac, DS28E25);
+}
+
+error_code DS28EL25::continueWriteAuthSegment(const Segment & newData,
+                                              const Hash & mac) {
+  return doContinueWriteAuthSegment(newData, mac, DS28E25);
+}
+
+error_code DS28EL25::readAllBlockProtection(
+    array<BlockProtection, protectionBlocks> & protection) const {
+  return doReadAllBlockProtection(protection.data(), protection.size(),
+                                  DS28E25);
+}
+
+error_code DS28E25::loadSecret(bool lock) { return doLoadSecret(lock, false); }
+
+error_code DS28E25::computeSecret(int pageNum, bool lock) {
+  return doComputeSecret(pageNum, lock, false);
+}
+
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS28E15_22_25.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,539 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_DS28E15_22_25
+#define MaximInterface_DS28E15_22_25
+
+#include <MaximInterface/Links/OneWireMaster.hpp>
+#include <MaximInterface/Links/SelectRom.hpp>
+#include <MaximInterface/Links/Sleep.hpp>
+#include <MaximInterface/Utilities/array.hpp>
+#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/ManId.hpp>
+#include <MaximInterface/Utilities/Sha256.hpp>
+
+namespace MaximInterface {
+
+/// Interface to the DS28E15/22/25 series of authenticators
+/// including low power variants.
+class DS28E15_22_25 {
+public:
+  enum ErrorValue { CrcError = 1, OperationFailure };
+
+  /// Holds the contents of a device memory segment.
+  typedef array<uint_least8_t, 4> Segment;
+
+  /// Holds the contents of a device memory page.
+  typedef array<uint_least8_t, 32> Page;
+
+  /// Number of segments per page.
+  static const int segmentsPerPage = Page::csize / Segment::csize;
+
+  /// Holds the contents of the device scratchpad.
+  typedef array<uint_least8_t, 32> Scratchpad;
+
+  /// Container for the device personality. 
+  struct Personality {
+    uint_least8_t PB1;
+    uint_least8_t PB2;
+    ManId manId;
+    
+    bool secretLocked() const { return PB2 & 0x01; }
+  };
+
+  /// Represents the status of a memory protection block.
+  class BlockProtection {
+  private:
+    static const unsigned int readProtectionMask = 0x80,
+                              writeProtectionMask = 0x40,
+                              eepromEmulationMask = 0x20,
+                              authProtectionMask = 0x10,
+                              blockNumMask = 0x0F;
+    uint_least8_t status;
+
+  public:
+    explicit BlockProtection(uint_least8_t status = 0x00) : status(status) {}
+    MaximInterface_EXPORT BlockProtection(bool readProtection,
+                                          bool writeProtection,
+                                          bool eepromEmulation,
+                                          bool authProtection,
+                                          int blockNum);
+
+    /// Get the byte representation used by the device.
+    uint_least8_t statusByte() const { return status; }
+    /// Set the byte representation used by the device.
+    void setStatusByte(uint_least8_t status) { this->status = status; }
+
+    /// Get the Block Number which is indexed from zero.
+    int blockNum() const { return (status & blockNumMask); }
+    /// Set the Block Number which is indexed from zero.
+    MaximInterface_EXPORT void setBlockNum(int blockNum);
+
+    /// Get the Read Protection status.
+    /// @returns True if Read Protection is enabled.
+    bool readProtection() const {
+      return ((status & readProtectionMask) == readProtectionMask);
+    }
+    /// Set the Read Protection status.
+    MaximInterface_EXPORT void setReadProtection(bool readProtection);
+
+    /// Get the Write Protection status.
+    /// @returns True if Write Protection is enabled.
+    bool writeProtection() const {
+      return ((status & writeProtectionMask) == writeProtectionMask);
+    }
+    /// Set the Write Protection status.
+    MaximInterface_EXPORT void setWriteProtection(bool writeProtection);
+
+    /// Get the EEPROM Emulation Mode status.
+    /// @returns True if EEPROM Emulation Mode is enabled.
+    bool eepromEmulation() const {
+      return ((status & eepromEmulationMask) == eepromEmulationMask);
+    }
+    /// Set the EEPROM Emulation Mode status.
+    MaximInterface_EXPORT void setEepromEmulation(bool eepromEmulation);
+
+    /// Get the Authentication Protection status.
+    /// @returns True if Authentication Protection is enabled.
+    bool authProtection() const {
+      return ((status & authProtectionMask) == authProtectionMask);
+    }
+    /// Set the Authentication Protection status.
+    MaximInterface_EXPORT void setAuthProtection(bool authProtection);
+
+    /// Check if no protection options are enabled.
+    /// @returns True if no protection options are enabled.
+    MaximInterface_EXPORT bool noProtection() const;
+  };
+
+  /// Format data to hash for an Authenticated Write to a memory segment.
+  /// @param pageNum Page number for write operation.
+  /// @param segmentNum Segment number within page for write operation.
+  /// @param[in] newData New data to write to the segment.
+  /// @param[in] oldData Existing data contained in the segment.
+  /// @param[in] romId 1-Wire ROM ID of the device.
+  /// @param[in] manId Manufacturer ID of the device.
+  MaximInterface_EXPORT static Sha256::WriteMacData
+  createSegmentWriteMacData(int pageNum, int segmentNum,
+                            const Segment & newData, const Segment & oldData,
+                            const RomId & romId, const ManId & manId);
+
+  /// Format data to hash for an Authenticated Write to a memory protection block.
+  /// @param[in] newProtection New protection status to write.
+  /// @param[in] oldProtection Existing protection status in device.
+  /// @param[in] romId 1-Wire ROM ID of the device.
+  /// @param[in] manId Manufacturer ID of the device.
+  MaximInterface_EXPORT static Sha256::WriteMacData
+  createProtectionWriteMacData(const BlockProtection & newProtection,
+                               const BlockProtection & oldProtection,
+                               const RomId & romId, const ManId & manId);
+
+  /// Format data to hash to compute the next secret from the existing secret.
+  /// @param[in] bindingPage Binding data from a device memory page.
+  /// @param bindingPageNum Number of the page where the binding data is from.
+  /// @param[in] partialSecret Partial secret data from the device scratchpad.
+  /// @param[in] romId 1-Wire ROM ID of the device.
+  /// @param[in] manId Manufacturer ID of the device.
+  MaximInterface_EXPORT static Sha256::SlaveSecretData
+  createSlaveSecretData(const Page & bindingPage, int bindingPageNum,
+                        const Scratchpad & partialSecret, const RomId & romId,
+                        const ManId & manId);
+
+  /// Format data to hash for device authentication.
+  /// @param[in] pageData Data from a device memory page.
+  /// @param pageNum Number of the page to use data from.
+  /// @param[in] challenge Random challenge to prevent replay attacks.
+  /// @param[in] romId 1-Wire ROM ID of the device.
+  /// @param[in] manId Manufacturer ID of the device.
+  MaximInterface_EXPORT static Sha256::AuthMacData
+  createAuthMacData(const Page & pageData, int pageNum,
+                    const Scratchpad & challenge, const RomId & romId,
+                    const ManId & manId);
+
+  /// Format datat to hash for device authentication using anonymous mode.
+  /// @param[in] pageData Data from a device memory page.
+  /// @param pageNum Number of the page to use data from.
+  /// @param[in] challenge Random challenge to prevent replay attacks.
+  /// @param[in] manId Manufacturer ID of the device.
+  MaximInterface_EXPORT static Sha256::AuthMacData
+  createAnonAuthMacData(const Page & pageData, int pageNum,
+                        const Scratchpad & challenge, const ManId & manId);
+
+  void setSleep(const Sleep & sleep) { this->sleep = &sleep; }
+  void setMaster(OneWireMaster & master) { this->master = &master; }
+  void setSelectRom(const SelectRom & selectRom) {
+    this->selectRom = selectRom;
+  }
+
+  // Const member functions should not affect the state of the memory,
+  // block protection, or secret on the device.
+
+  /// Read memory segment using the Read Memory command on the device.
+  /// @param pageNum Page number for read operation.
+  /// @param segmentNum Segment number within page for read operation.
+  /// @param[out] data Buffer to read data from the segment into.
+  MaximInterface_EXPORT error_code readSegment(int pageNum, int segmentNum,
+                                               Segment & data) const;
+
+  /// Continue an in-progress readSegment operation.
+  /// @note A CRC16 will encountered after reading the last segment of a page.
+  /// @param[out] data Buffer to read data from the segment into.
+  MaximInterface_EXPORT error_code continueReadSegment(Segment & data) const;
+
+  /// Write memory segment using the Write Memory command.
+  /// @note 1-Wire ROM selection should have already occurred.
+  /// @param pageNum Page number for write operation.
+  /// @param segmentNum Segment number within page for write operation.
+  /// @param[in] data Data to write to the memory segment.
+  MaximInterface_EXPORT error_code writeSegment(int pageNum, int segmentNum,
+                                                const Segment & data);
+
+  /// Continue an in-progress Write Memory command.
+  /// @param[in] data Data to write to the memory segment.
+  MaximInterface_EXPORT error_code continueWriteSegment(const Segment & data);
+
+  /// Read memory page using the Read Memory command on the device.
+  /// @param pageNum Page number for write operation.
+  /// @param[out] rdbuf Buffer to read data from the page into.
+  MaximInterface_EXPORT error_code readPage(int pageNum, Page & rdbuf) const;
+
+  /// Continue an in-progress readPageOperation.
+  /// @param[out] rdbuf Buffer to read data from the page into.
+  MaximInterface_EXPORT error_code continueReadPage(Page & rdbuf) const;
+
+  /// Perform a Compute Page MAC command on the device.
+  /// Read back the MAC and verify the CRC16.
+  /// @param pageNum Page number to use for the computation.
+  /// @param anon True to compute in anonymous mode where ROM ID is not used.
+  /// @param[out] mac The device computed MAC.
+  MaximInterface_EXPORT error_code computeReadPageMac(int pageNum, bool anon,
+                                                      Sha256::Hash & mac) const;
+
+  /// Update the status of a memory protection block using the
+  /// Write Page Protection command.
+  /// @param[in] Desired protection status for the block.
+  ///            It is not possible to disable existing protections.
+  /// @param continuing True to continue a previous Write Page Protection command.
+  ///                   False to begin a new command.
+  MaximInterface_EXPORT error_code
+  writeBlockProtection(const BlockProtection & protection);
+
+  /// Update the status of a memory protection block using the
+  /// Authenticated Write Page Protection command.
+  /// @param[in] newProtection New protection status to write.
+  /// @param[in] mac Write MAC computed for this operation.
+  MaximInterface_EXPORT error_code writeAuthBlockProtection(
+      const BlockProtection & newProtection, const Sha256::Hash & mac);
+
+  /// Perform Load and Lock Secret command on the device.
+  /// @note The secret should already be stored in the scratchpad on the device.
+  /// @param lock Prevent further changes to the secret on the device after loading.
+  MaximInterface_EXPORT error_code loadSecret(bool lock);
+
+  /// Perform a Compute and Lock Secret command on the device.
+  /// @param pageNum Page number to use as the binding data.
+  /// @param lock Prevent further changes to the secret on the device after computing.
+  MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock);
+
+  /// Read the personality bytes using the Read Status command.
+  /// @param[out] personality Receives personality read from device.
+  MaximInterface_EXPORT error_code
+  readPersonality(Personality & personality) const;
+
+  MaximInterface_EXPORT static const error_category & errorCategory();
+
+protected:
+  enum Variant { DS28E15, DS28E22, DS28E25 };
+
+  DS28E15_22_25(const Sleep & sleep, OneWireMaster & master,
+                const SelectRom & selectRom)
+      : selectRom(selectRom), master(&master), sleep(&sleep) {}
+
+  error_code doWriteScratchpad(const Scratchpad & data, Variant variant);
+
+  error_code doReadScratchpad(Scratchpad & data, Variant variant) const;
+
+  error_code doReadBlockProtection(int blockNum, BlockProtection & protection,
+                                   Variant variant) const;
+
+  error_code doWriteAuthSegment(int pageNum, int segmentNum,
+                                const Segment & newData,
+                                const Sha256::Hash & mac, Variant variant);
+
+  error_code doContinueWriteAuthSegment(const Segment & newData,
+                                        const Sha256::Hash & mac,
+                                        Variant variant);
+
+  error_code doReadAllBlockProtection(BlockProtection * protection,
+                                      size_t protectionLen,
+                                      Variant variant) const;
+
+  error_code doLoadSecret(bool lock, bool lowPower);
+
+  error_code doComputeSecret(int pageNum, bool lock, bool lowPower);
+
+private:
+  enum Command {
+    WriteMemory = 0x55,
+    ReadMemory = 0xF0,
+    LoadAndLockSecret = 0x33,
+    ComputeAndLockSecret = 0x3C,
+    ReadWriteScratchpad = 0x0F,
+    ComputePageMac = 0xA5,
+    ReadStatus = 0xAA,
+    WriteBlockProtection = 0xC3,
+    AuthWriteMemory = 0x5A,
+    AuthWriteBlockProtection = 0xCC,
+  };
+
+  error_code doWriteAuthSegment(const Segment & newData,
+                                const Sha256::Hash & mac, Variant variant,
+                                bool continuing);
+
+  error_code writeCommandWithCrc(
+      Command command, uint_least8_t parameter,
+      OneWireMaster::Level level = OneWireMaster::NormalLevel) const;
+
+  SelectRom selectRom;
+  OneWireMaster * master;
+  const Sleep * sleep;
+};
+
+inline error_code make_error_code(DS28E15_22_25::ErrorValue e) {
+  return error_code(e, DS28E15_22_25::errorCategory());
+}
+
+inline bool operator==(DS28E15_22_25::BlockProtection lhs,
+                       DS28E15_22_25::BlockProtection rhs) {
+  return lhs.statusByte() == rhs.statusByte();
+}
+
+inline bool operator!=(DS28E15_22_25::BlockProtection lhs,
+                       DS28E15_22_25::BlockProtection rhs) {
+  return !operator==(lhs, rhs);
+}
+
+/// Interface to the DS28EL15 (low power) authenticator.
+class DS28EL15 : public DS28E15_22_25 {
+public:
+  // DS28E15_22_25 traits
+  static const int memoryPages = 2;
+  static const int protectionBlocks = 4;
+
+  DS28EL15(const Sleep & sleep, OneWireMaster & master,
+           const SelectRom & selectRom)
+      : DS28E15_22_25(sleep, master, selectRom) {}
+
+  /// Perform Write Scratchpad operation on the device.
+  /// @param[in] data Data to write to the scratchpad.
+  MaximInterface_EXPORT error_code writeScratchpad(const Scratchpad & data);
+
+  /// Perform a Read Scratchpad operation on the device.
+  /// @param[out] data Buffer to read data from the scratchpad into.
+  MaximInterface_EXPORT error_code readScratchpad(Scratchpad & data) const;
+
+  /// Read the status of a memory protection block using the Read Status command.
+  /// @param blockNum Block number to to read status of.
+  /// @param[out] protection Receives protection status read from device.
+  MaximInterface_EXPORT error_code
+  readBlockProtection(int blockNum, BlockProtection & protection) const;
+
+  /// Write memory segment using the Authenticated Write Memory command.
+  /// @param pageNum Page number for write operation.
+  /// @param segmentNum Segment number within page for write operation.
+  /// @param[in] newData New data to write to the segment.
+  /// @param[in] mac Write MAC computed for this operation.
+  MaximInterface_EXPORT error_code writeAuthSegment(int pageNum, int segmentNum,
+                                                    const Segment & newData,
+                                                    const Sha256::Hash & mac);
+
+  /// Continue an in-progress Authenticated Write Memory command.
+  /// @param[in] newData New data to write to the segment.
+  /// @param[in] mac Write MAC computed for this operation.
+  MaximInterface_EXPORT error_code
+  continueWriteAuthSegment(const Segment & newData, const Sha256::Hash & mac);
+
+  /// Read the status of all memory protection blocks using the Read Status command.
+  /// @param[out] protection Receives protection statuses read from device.
+  MaximInterface_EXPORT error_code readAllBlockProtection(
+      array<BlockProtection, protectionBlocks> & protection) const;
+};
+
+/// Interface to the DS28E15 authenticator.
+class DS28E15 : public DS28EL15 {
+public:
+  DS28E15(const Sleep & sleep, OneWireMaster & master,
+          const SelectRom & selectRom)
+      : DS28EL15(sleep, master, selectRom) {}
+
+  /// Perform Load and Lock Secret command on the device.
+  /// @note The secret should already be stored in the scratchpad on the device.
+  /// @param lock Prevent further changes to the secret on the device after loading.
+  MaximInterface_EXPORT error_code loadSecret(bool lock);
+
+  /// Perform a Compute and Lock Secret command on the device.
+  /// @param pageNum Page number to use as the binding data.
+  /// @param lock Prevent further changes to the secret on the device after computing.
+  MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock);
+};
+
+/// Interface to the DS28EL22 (low power) authenticator.
+class DS28EL22 : public DS28E15_22_25 {
+public:
+  // DS28E15_22_25 traits
+  static const int memoryPages = 8;
+  static const int protectionBlocks = 4;
+
+  DS28EL22(const Sleep & sleep, OneWireMaster & master,
+           const SelectRom & selectRom)
+      : DS28E15_22_25(sleep, master, selectRom) {}
+
+  /// Perform Write Scratchpad operation on the device.
+  /// @param[in] data Data to write to the scratchpad.
+  MaximInterface_EXPORT error_code writeScratchpad(const Scratchpad & data);
+
+  /// Perform a Read Scratchpad operation on the device.
+  /// @param[out] data Buffer to read data from the scratchpad into.
+  MaximInterface_EXPORT error_code readScratchpad(Scratchpad & data) const;
+
+  /// Read the status of a memory protection block using the Read Status command.
+  /// @param blockNum Block number to to read status of.
+  /// @param[out] protection Receives protection status read from device.
+  MaximInterface_EXPORT error_code
+  readBlockProtection(int blockNum, BlockProtection & protection) const;
+
+  /// Write memory segment using the Authenticated Write Memory command.
+  /// @param pageNum Page number for write operation.
+  /// @param segmentNum Segment number within page for write operation.
+  /// @param[in] newData New data to write to the segment.
+  /// @param[in] mac Write MAC computed for this operation.
+  MaximInterface_EXPORT error_code writeAuthSegment(int pageNum, int segmentNum,
+                                                    const Segment & newData,
+                                                    const Sha256::Hash & mac);
+
+  /// Continue an in-progress Authenticated Write Memory command.
+  /// @param[in] newData New data to write to the segment.
+  /// @param[in] mac Write MAC computed for this operation.
+  MaximInterface_EXPORT error_code
+  continueWriteAuthSegment(const Segment & newData, const Sha256::Hash & mac);
+
+  /// Read the status of all memory protection blocks using the Read Status command.
+  /// @param[out] protection Receives protection statuses read from device.
+  MaximInterface_EXPORT error_code readAllBlockProtection(
+      array<BlockProtection, protectionBlocks> & protection) const;
+};
+
+/// Interface to the DS28E22 authenticator.
+class DS28E22 : public DS28EL22 {
+public:
+  DS28E22(const Sleep & sleep, OneWireMaster & master,
+          const SelectRom & selectRom)
+      : DS28EL22(sleep, master, selectRom) {}
+
+  /// Perform Load and Lock Secret command on the device.
+  /// @note The secret should already be stored in the scratchpad on the device.
+  /// @param lock Prevent further changes to the secret on the device after loading.
+  MaximInterface_EXPORT error_code loadSecret(bool lock);
+
+  /// Perform a Compute and Lock Secret command on the device.
+  /// @param pageNum Page number to use as the binding data.
+  /// @param lock Prevent further changes to the secret on the device after computing.
+  MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock);
+};
+
+/// Interface to the DS28EL25 (low power) authenticator.
+class DS28EL25 : public DS28E15_22_25 {
+public:
+  // DS28E15_22_25 traits
+  static const int memoryPages = 16;
+  static const int protectionBlocks = 8;
+
+  DS28EL25(const Sleep & sleep, OneWireMaster & master,
+           const SelectRom & selectRom)
+      : DS28E15_22_25(sleep, master, selectRom) {}
+
+  /// Perform Write Scratchpad operation on the device.
+  /// @param[in] data Data to write to the scratchpad.
+  MaximInterface_EXPORT error_code writeScratchpad(const Scratchpad & data);
+
+  /// Perform a Read Scratchpad operation on the device.
+  /// @param[out] data Buffer to read data from the scratchpad into.
+  MaximInterface_EXPORT error_code readScratchpad(Scratchpad & data) const;
+
+  /// Read the status of a memory protection block using the Read Status command.
+  /// @param blockNum Block number to to read status of.
+  /// @param[out] protection Receives protection status read from device.
+  MaximInterface_EXPORT error_code
+  readBlockProtection(int blockNum, BlockProtection & protection) const;
+
+  /// Write memory segment using the Authenticated Write Memory command.
+  /// @param pageNum Page number for write operation.
+  /// @param segmentNum Segment number within page for write operation.
+  /// @param[in] newData New data to write to the segment.
+  /// @param[in] mac Write MAC computed for this operation.
+  MaximInterface_EXPORT error_code writeAuthSegment(int pageNum, int segmentNum,
+                                                    const Segment & newData,
+                                                    const Sha256::Hash & mac);
+
+  /// Continue an in-progress Authenticated Write Memory command.
+  /// @param[in] newData New data to write to the segment.
+  /// @param[in] mac Write MAC computed for this operation.
+  MaximInterface_EXPORT error_code
+  continueWriteAuthSegment(const Segment & newData, const Sha256::Hash & mac);
+
+  /// Read the status of all memory protection blocks using the Read Status command.
+  /// @param[out] protection Receives protection statuses read from device.
+  MaximInterface_EXPORT error_code readAllBlockProtection(
+      array<BlockProtection, protectionBlocks> & protection) const;
+};
+
+/// Interface to the DS28E25 authenticator.
+class DS28E25 : public DS28EL25 {
+public:
+  DS28E25(const Sleep & sleep, OneWireMaster & master,
+          const SelectRom & selectRom)
+      : DS28EL25(sleep, master, selectRom) {}
+
+  /// Perform Load and Lock Secret command on the device.
+  /// @note The secret should already be stored in the scratchpad on the device.
+  /// @param lock Prevent further changes to the secret on the device after loading.
+  MaximInterface_EXPORT error_code loadSecret(bool lock);
+
+  /// Perform a Compute and Lock Secret command on the device.
+  /// @param pageNum Page number to use as the binding data.
+  /// @param lock Prevent further changes to the secret on the device after computing.
+  MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock);
+};
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS28E17.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,279 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <stddef.h>
+#include <MaximInterface/Links/OneWireMaster.hpp>
+#include <MaximInterface/Utilities/crc.hpp>
+#include <MaximInterface/Utilities/Error.hpp>
+#include "DS28E17.hpp"
+
+namespace MaximInterface {
+
+error_code DS28E17::writeDataWithStop(uint_least8_t I2C_addr,
+                                      const uint_least8_t * data,
+                                      size_t data_len,
+                                      uint_least8_t * wr_status) {
+  return sendPacket(WriteDataWithStopCmd, &I2C_addr, data, data_len, NULL, 0,
+                    wr_status);
+}
+
+error_code DS28E17::writeDataNoStop(uint_least8_t I2C_addr,
+                                    const uint_least8_t * data, size_t data_len,
+                                    uint_least8_t * wr_status) {
+  return sendPacket(WriteDataNoStopCmd, &I2C_addr, data, data_len, NULL, 0,
+                    wr_status);
+}
+
+error_code DS28E17::writeDataOnly(const uint_least8_t * data, size_t data_len,
+                                  uint_least8_t * wr_status) {
+  return sendPacket(WriteDataOnlyCmd, NULL, data, data_len, NULL, 0, wr_status);
+}
+
+error_code DS28E17::writeDataOnlyWithStop(const uint_least8_t * data,
+                                          size_t data_len,
+                                          uint_least8_t * wr_status) {
+  return sendPacket(WriteDataOnlyWithStopCmd, NULL, data, data_len, NULL, 0,
+                    wr_status);
+}
+
+error_code DS28E17::writeReadDataWithStop(uint_least8_t I2C_addr,
+                                          const uint_least8_t * write_data,
+                                          size_t write_data_len,
+                                          uint_least8_t * read_data,
+                                          size_t read_data_len,
+                                          uint_least8_t * wr_status) {
+  return sendPacket(WriteReadDataWithStopCmd, &I2C_addr, write_data,
+                    write_data_len, read_data, read_data_len, wr_status);
+}
+
+error_code DS28E17::readDataWithStop(uint_least8_t I2C_addr,
+                                     uint_least8_t * data, size_t data_len) {
+  return sendPacket(ReadDataWithStopCmd, &I2C_addr, NULL, 0, data, data_len,
+                    NULL);
+}
+
+error_code DS28E17::writeConfigReg(I2CSpeed speed) {
+  error_code result = selectRom(*master);
+  if (!result) {
+    // Send CMD and Data
+    const uint_least8_t send_block[] = {WriteConfigurationCmd,
+                                        static_cast<uint_least8_t>(speed)};
+    result = master->writeBlock(send_block,
+                                sizeof(send_block) / sizeof(send_block[0]));
+  }
+  return result;
+}
+
+error_code DS28E17::readConfigReg(I2CSpeed & speed) {
+  error_code result = selectRom(*master);
+  if (!result) {
+    // Send CMD and receive Data
+    result = master->writeByte(ReadConfigurationCmd);
+    if (!result) {
+      uint_least8_t config;
+      result = master->readByte(config);
+      if (!result) {
+        switch (config) {
+        case Speed100kHz:
+        case Speed400kHz:
+        case Speed900kHz:
+          speed = static_cast<I2CSpeed>(config);
+          break;
+
+        default:
+          result = make_error_code(OutOfRangeError);
+          break;
+        }
+      }
+    }
+  }
+  return result;
+}
+
+error_code DS28E17::enableSleepMode() {
+  error_code result = selectRom(*master);
+  if (!result) {
+    // Send CMD
+    result = master->writeByte(EnableSleepModeCmd);
+  }
+  return result;
+}
+
+error_code DS28E17::readDeviceRevision(uint_least8_t & rev) {
+  error_code result = selectRom(*master);
+  if (!result) {
+    // Send CMD and receive Data
+    result = master->writeByte(ReadDeviceRevisionCmd);
+    if (!result) {
+      result = master->readByte(rev);
+    }
+  }
+  return result;
+}
+
+error_code DS28E17::sendPacket(Command command, const uint_least8_t * I2C_addr,
+                               const uint_least8_t * write_data,
+                               size_t write_data_len, uint_least8_t * read_data,
+                               size_t read_data_len,
+                               uint_least8_t * wr_status) {
+  const int pollLimit = 10000;
+  const size_t minDataLen = 1;
+  const size_t maxDataLen = 255;
+
+  if ((write_data &&
+       (write_data_len < minDataLen || write_data_len > maxDataLen)) ||
+      (read_data &&
+       (read_data_len < minDataLen || read_data_len > maxDataLen))) {
+    return make_error_code(OutOfRangeError);
+  }
+
+  error_code result = selectRom(*master);
+  if (result) {
+    return result;
+  }
+  uint_fast16_t crc16 = calculateCrc16(command);
+  result = master->writeByte(command);
+  if (result) {
+    return result;
+  }
+  if (I2C_addr) {
+    crc16 = calculateCrc16(*I2C_addr, crc16);
+    result = master->writeByte(*I2C_addr);
+    if (result) {
+      return result;
+    }
+  }
+  if (write_data) {
+    crc16 = calculateCrc16(static_cast<uint_fast8_t>(write_data_len), crc16);
+    result = master->writeByte(static_cast<uint_least8_t>(write_data_len));
+    if (result) {
+      return result;
+    }
+    crc16 = calculateCrc16(write_data, write_data_len, crc16);
+    result = master->writeBlock(write_data, write_data_len);
+    if (result) {
+      return result;
+    }
+  }
+  if (read_data) {
+    crc16 = calculateCrc16(static_cast<uint_fast8_t>(read_data_len), crc16);
+    result = master->writeByte(static_cast<uint_least8_t>(read_data_len));
+    if (result) {
+      return result;
+    }
+  }
+  crc16 ^= 0xFFFFU;
+  const uint_least8_t crc16Bytes[] = {static_cast<uint_least8_t>(crc16),
+                                      static_cast<uint_least8_t>(crc16 >> 8)};
+  result = master->writeBlock(crc16Bytes,
+                              sizeof(crc16Bytes) / sizeof(crc16Bytes[0]));
+  if (result) {
+    return result;
+  }
+  // Poll for Zero 1-Wire bit and return if an error occurs
+  int poll_count = 0;
+  bool recvbit;
+  do {
+    if (poll_count++ < pollLimit) {
+      return make_error_code(TimeoutError);
+    }
+    result = master->readBit(recvbit);
+    if (result) {
+      return result;
+    }
+  } while (recvbit);
+  uint_least8_t status;
+  result = master->readByte(status);
+  if (result) {
+    return result;
+  }
+  if ((status & 0x1) == 0x1) {
+    return make_error_code(InvalidCrc16Error);
+  }
+  if ((status & 0x2) == 0x2) {
+    return make_error_code(AddressNackError);
+  }
+  if ((status & 0x8) == 0x8) {
+    return make_error_code(InvalidStartError);
+  }
+  if (write_data) {
+    result = master->readByte(status);
+    if (result) {
+      return result;
+    }
+    if (wr_status) {
+      *wr_status = status;
+    }
+    if (status != 0) {
+      return make_error_code(WriteNackError);
+    }
+  }
+  if (read_data) {
+    result = master->readBlock(read_data, read_data_len);
+  }
+  return result;
+}
+
+const error_category & DS28E17::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "DS28E17"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case TimeoutError:
+        return "Timeout Error";
+
+      case OutOfRangeError:
+        return "Out of Range Error";
+
+      case InvalidCrc16Error:
+        return "Invalid CRC16 Error";
+
+      case AddressNackError:
+        return "Address Nack Error";
+
+      case InvalidStartError:
+        return "Invalid Start Error";
+
+      case WriteNackError:
+        return "Write Nack Error";
+
+      default:
+        return defaultErrorMessage(condition);
+      }
+    }
+  } instance;
+  return instance;
+}
+
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS28E17.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,212 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_DS28E17
+#define MaximInterface_DS28E17
+
+#include <stdint.h>
+#include <MaximInterface/Links/SelectRom.hpp>
+#include <MaximInterface/Utilities/Export.h>
+
+namespace MaximInterface {
+
+/// DS28E17 1-Wire®-to-I2C Master Bridge
+/// @details The DS28E17 is a 1-Wire slave to I2C master bridge
+/// device that interfaces directly to I2C slaves at standard
+/// (100kHz max) or fast (400kHz max). Data transfers serially by
+/// means of the 1-Wire® protocol, which requires only a single data
+/// lead and a ground return. Every DS28E17 is guaranteed to have a
+/// unique 64-bit ROM registration number that serves as a node
+/// address in the 1-Wire network. Multiple DS28E17 devices can
+/// coexist with other devices in the 1-Wire network and be accessed
+/// individually without affecting other devices. The DS28E17 allows
+/// using complex I2C devices such as display controllers, ADCs, DACs,
+/// I2C sensors, etc. in a 1-Wire environment. Each self-timed DS28E17
+/// provides 1-Wire access for a single I2C interface.
+class DS28E17 {
+public:
+  enum ErrorValue {
+    TimeoutError = 1,
+    OutOfRangeError,
+    InvalidCrc16Error,
+    AddressNackError,
+    InvalidStartError,
+    WriteNackError
+  };
+
+  enum I2CSpeed { Speed100kHz, Speed400kHz, Speed900kHz };
+
+  DS28E17(OneWireMaster & master, const SelectRom & selectRom)
+      : selectRom(selectRom), master(&master) {}
+
+  void setMaster(OneWireMaster & master) { this->master = &master; }
+  void setSelectRom(const SelectRom & selectRom) {
+    this->selectRom = selectRom;
+  }
+
+  /// Write Data With Stop command.
+  /// @details Output on I2C: S, Address + Write, Write Data [1-255], P
+  /// @param[in] I2C_addr
+  /// I2C slave address. The least significant bit of the I2C
+  /// address is automatically cleared by the command.
+  /// @param[in] data I2C data to write.
+  /// @param[in] data_len Length of data. Valid from 1-255.
+  /// @param[out] wr_status
+  /// Indicates which write byte NACK’d. A value of 00h indicates all bytes
+  /// were acknowledged by the slave. A non-zero value indicates the byte number
+  /// that NACK’d. May be set to NULL.
+  MaximInterface_EXPORT error_code
+  writeDataWithStop(uint_least8_t I2C_addr, const uint_least8_t * data,
+                    size_t data_len, uint_least8_t * wr_status = NULL);
+
+  /// Write Data No Stop command.
+  /// @details Output on I2C: S, Address + Write, Write Data [1-255]
+  /// @param[in] I2C_addr
+  /// I2C slave address. The least significant bit of the I2C address
+  /// is automatically cleared by the command.
+  /// @param[in] data I2C data to write.
+  /// @param[in] data_len Length of data. Valid from 1-255.
+  /// @param[out] wr_status
+  /// Indicates which write byte NACK’d. A value of 00h indicates all bytes
+  /// were acknowledged by the slave. A non-zero value indicates the byte number
+  /// that NACK’d. May be set to NULL.
+  MaximInterface_EXPORT error_code
+  writeDataNoStop(uint_least8_t I2C_addr, const uint_least8_t * data,
+                  size_t data_len, uint_least8_t * wr_status = NULL);
+
+  /// Write Data Only command.
+  /// @details Output on I2C: Write Data [1-255]
+  /// @param[in] data I2C data to write.
+  /// @param[in] data_len Length of data. Valid from 1-255.
+  /// @param[out] wr_status
+  /// Indicates which write byte NACK’d. A value of 00h indicates all bytes
+  /// were acknowledged by the slave. A non-zero value indicates the byte number
+  /// that NACK’d. May be set to NULL.
+  MaximInterface_EXPORT error_code
+  writeDataOnly(const uint_least8_t * data, size_t data_len,
+                uint_least8_t * wr_status = NULL);
+
+  /// Write Data Only With Stop command.
+  /// @details Output on I2C: Write Data [1-255], P
+  /// @param[in] data I2C data to write.
+  /// @param[in] data_len Length of data. Valid from 1-255.
+  /// @param[out] wr_status
+  /// Indicates which write byte NACK’d. A value of 00h indicates all bytes
+  /// were acknowledged by the slave. A non-zero value indicates the byte number
+  /// that NACK’d. May be set to NULL.
+  MaximInterface_EXPORT error_code
+  writeDataOnlyWithStop(const uint_least8_t * data, size_t data_len,
+                        uint_least8_t * wr_status = NULL);
+
+  /// Write, Read Data With Stop command.
+  /// @details Output on I2C:
+  /// S, Slave Address + Write, Write Data [1-255],
+  /// Sr, Address + Read, Read Data [1-255], P (NACK last read byte)
+  /// @param[in] I2C_addr
+  /// I2C slave address. The least significant bit of the I2C address
+  /// is automatically cleared and set by the command.
+  /// @param[in] write_data I2C data to write.
+  /// @param[in] write_data_len Length of write_data. Valid from 1-255.
+  /// @param[out] read_data I2C data that was read.
+  /// @param[in] read_data_len Length of read_data. Valid from 1-255.
+  /// @param[out] wr_status
+  /// Indicates which write byte NACK’d. A value of 00h indicates all bytes
+  /// were acknowledged by the slave. A non-zero value indicates the byte number
+  /// that NACK’d. May be set to NULL.
+  MaximInterface_EXPORT error_code writeReadDataWithStop(
+      uint_least8_t I2C_addr, const uint_least8_t * write_data,
+      size_t write_data_len, uint_least8_t * read_data, size_t read_data_len,
+      uint_least8_t * wr_status = NULL);
+
+  /// Read Data With Stop command.
+  /// @details Output on I2C:
+  /// S, Slave Address + Read, Read Data [1-255], P (NACK last read byte)
+  /// @param[in]  I2C_addr
+  /// I2C slave address. The least significant bit of the I2C address
+  /// is automatically set by the command.
+  /// @param[out] data I2C data that was read.
+  /// @param[in] data_len Length of data. Valid from 1-255.
+  MaximInterface_EXPORT error_code readDataWithStop(uint_least8_t I2C_addr,
+                                                    uint_least8_t * data,
+                                                    size_t data_len);
+
+  /// Write to Configuration Register of DS28E17.
+  MaximInterface_EXPORT error_code writeConfigReg(I2CSpeed speed);
+
+  /// Read the Configuration Register of DS28E17.
+  /// @param[out] speed Speed read from configuration register.
+  MaximInterface_EXPORT error_code readConfigReg(I2CSpeed & speed);
+
+  /// The Enable Sleep Mode command puts the device into a low current mode.
+  /// @details All 1-Wire communication is ignored until woken up. Immediately
+  /// after the command, the device monitors the WAKEUP input pin and exits
+  /// sleep mode on a rising edge.
+  MaximInterface_EXPORT error_code enableSleepMode();
+
+  /// Read the Device Revision of DS28E17.
+  /// @details The upper nibble is the major revision,
+  /// and the lower nibble is the minor revision.
+  /// @param[out] rev Device Revision.
+  MaximInterface_EXPORT error_code readDeviceRevision(uint_least8_t & rev);
+
+  MaximInterface_EXPORT static const error_category & errorCategory();
+
+private:
+  enum Command {
+    WriteDataWithStopCmd = 0x4B,
+    WriteDataNoStopCmd = 0x5A,
+    WriteDataOnlyCmd = 0x69,
+    WriteDataOnlyWithStopCmd = 0x78,
+    ReadDataWithStopCmd = 0x87,
+    WriteReadDataWithStopCmd = 0x2D,
+    WriteConfigurationCmd = 0xD2,
+    ReadConfigurationCmd = 0xE1,
+    EnableSleepModeCmd = 0x1E,
+    ReadDeviceRevisionCmd = 0xC3
+  };
+
+  error_code sendPacket(Command command, const uint_least8_t * I2C_addr,
+                        const uint_least8_t * write_data, size_t write_data_len,
+                        uint_least8_t * read_data, size_t read_data_len,
+                        uint_least8_t * wr_status);
+
+  SelectRom selectRom;
+  OneWireMaster * master;
+};
+
+inline error_code make_error_code(DS28E17::ErrorValue e) {
+  return error_code(e, DS28E17::errorCategory());
+}
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS9400.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,75 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include "DS9400.hpp"
+
+namespace MaximInterface {
+
+error_code DS9400::start() { return uart->writeByte('S'); }
+
+error_code DS9400::start(uint_least8_t address) {
+  error_code result = start();
+  if (!result) {
+    result = writeByte(address);
+  }
+  return result;
+}
+
+error_code DS9400::stop() { return uart->writeByte('P'); }
+
+error_code DS9400::writeByte(uint_least8_t data) {
+  const uint_least8_t packet[] = {'Q', data};
+  error_code result = uart->clearReadBuffer();
+  if (!result) {
+    result = uart->writeBlock(packet, sizeof(packet) / sizeof(packet[0]));
+    if (!result) {
+      result = uart->readByte(data);
+      if (!result && data != 0) {
+        result = make_error_code(I2CMaster::NackError);
+      }
+    }
+  }
+  return result;
+}
+
+error_code DS9400::readByte(AckStatus status, uint_least8_t & data) {
+  error_code result = uart->clearReadBuffer();
+  if (!result) {
+    result = uart->writeByte(status == Ack ? 'R' : 'N');
+    if (!result) {
+      result = uart->readByte(data);
+    }
+  }
+  return result;
+}
+
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Devices/DS9400.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,61 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_DS9400
+#define MaximInterface_DS9400
+
+#include <MaximInterface/Links/I2CMaster.hpp>
+#include <MaximInterface/Links/Uart.hpp>
+#include <MaximInterface/Utilities/Export.h>
+
+namespace MaximInterface {
+
+class DS9400 : public I2CMaster {
+public:
+  explicit DS9400(Uart & uart) : uart(&uart) {}
+
+  void setUart(Uart & uart) { this->uart = &uart; }
+
+  MaximInterface_EXPORT error_code start();
+  MaximInterface_EXPORT virtual error_code start(uint_least8_t address);
+  MaximInterface_EXPORT virtual error_code stop();
+  MaximInterface_EXPORT virtual error_code writeByte(uint_least8_t data);
+  MaximInterface_EXPORT virtual error_code readByte(AckStatus status,
+                                                    uint_least8_t & data);
+
+private:
+  Uart * uart;
+};
+
+} // namespace MaximInterface
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/I2CMaster.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,104 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <MaximInterface/Utilities/Error.hpp>
+#include "I2CMaster.hpp"
+
+namespace MaximInterface {
+
+error_code I2CMaster::writeBlock(const uint_least8_t * data, size_t dataLen) {
+  error_code result;
+  for (size_t i = 0; (i < dataLen) && !result; i++) {
+    result = writeByte(data[i]);
+  }
+  return result;
+}
+
+error_code I2CMaster::writePacket(uint_least8_t address,
+                                  const uint_least8_t * data, size_t dataLen,
+                                  bool sendStop) {
+  error_code result = start(address & 0xFE);
+  if (!result) {
+    result = writeBlock(data, dataLen);
+  }
+  if (sendStop) {
+    error_code stopResult = stop();
+    if (!result) {
+      result = stopResult;
+    }
+  }
+  return result;
+}
+
+error_code I2CMaster::readBlock(AckStatus status, uint_least8_t * data,
+                                size_t dataLen) {
+  error_code result;
+  for (size_t i = 0; (i < dataLen) && !result; i++) {
+    result = readByte(i == (dataLen - 1) ? status : Ack, data[i]);
+  }
+  return result;
+}
+
+error_code I2CMaster::readPacket(uint_least8_t address, uint_least8_t * data,
+                                 size_t dataLen, bool sendStop) {
+  error_code result = start(address | 0x01);
+  if (!result) {
+    result = readBlock(Nack, data, dataLen);
+  }
+  if (sendStop) {
+    error_code stopResult = stop();
+    if (!result) {
+      result = stopResult;
+    }
+  }
+  return result;
+}
+
+const error_category & I2CMaster::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "I2CMaster"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case NackError:
+        return "Nack Error";
+
+      default:
+        return defaultErrorMessage(condition);
+      }
+    }
+  } instance;
+  return instance;
+}
+
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/I2CMaster.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,89 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_I2CMaster
+#define MaximInterface_I2CMaster
+
+#include <stddef.h>
+#include <stdint.h>
+#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/system_error.hpp>
+
+namespace MaximInterface {
+
+class I2CMaster {
+public:
+  enum ErrorValue {
+    NackError = 1 ///< Transaction stopped due to a NACK from the slave device.
+  };
+
+  enum AckStatus { Ack = 1, Nack = 0 };
+
+  virtual ~I2CMaster() {}
+
+  virtual error_code start(uint_least8_t address) = 0;
+  virtual error_code stop() = 0;
+  virtual error_code writeByte(uint_least8_t data) = 0;
+  MaximInterface_EXPORT virtual error_code
+  writeBlock(const uint_least8_t * data, size_t dataLen);
+  MaximInterface_EXPORT virtual error_code
+  writePacket(uint_least8_t address, const uint_least8_t * data, size_t dataLen,
+              bool sendStop);
+  error_code writePacket(uint_least8_t address, const uint_least8_t * data,
+                         size_t dataLen) {
+    return writePacket(address, data, dataLen, true);
+  }
+  virtual error_code readByte(AckStatus status, uint_least8_t & data) = 0;
+  MaximInterface_EXPORT virtual error_code
+  readBlock(AckStatus status, uint_least8_t * data, size_t dataLen);
+  MaximInterface_EXPORT virtual error_code readPacket(uint_least8_t address,
+                                                      uint_least8_t * data,
+                                                      size_t dataLen,
+                                                      bool sendStop);
+  error_code readPacket(uint_least8_t address, uint_least8_t * data,
+                        size_t dataLen) {
+    return readPacket(address, data, dataLen, true);
+  }
+
+  MaximInterface_EXPORT static const error_category & errorCategory();
+};
+
+inline error_code make_error_code(I2CMaster::ErrorValue e) {
+  return error_code(e, I2CMaster::errorCategory());
+}
+inline error_condition make_error_condition(I2CMaster::ErrorValue e) {
+  return error_condition(e, I2CMaster::errorCategory());
+}
+
+} // namespace MaximInterface
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/I2CMasterDecorator.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,74 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include "I2CMasterDecorator.hpp"
+
+namespace MaximInterface {
+
+error_code I2CMasterDecorator::start(uint_least8_t address) {
+  return i2c->start(address);
+}
+
+error_code I2CMasterDecorator::stop() { return i2c->stop(); }
+
+error_code I2CMasterDecorator::writeByte(uint_least8_t data) {
+  return i2c->writeByte(data);
+}
+
+error_code I2CMasterDecorator::writeBlock(const uint_least8_t * data,
+                                          size_t dataLen) {
+  return i2c->writeBlock(data, dataLen);
+}
+
+error_code I2CMasterDecorator::writePacket(uint_least8_t address,
+                                           const uint_least8_t * data,
+                                           size_t dataLen, bool sendStop) {
+  return i2c->writePacket(address, data, dataLen, sendStop);
+}
+
+error_code I2CMasterDecorator::readByte(AckStatus status,
+                                        uint_least8_t & data) {
+  return i2c->readByte(status, data);
+}
+
+error_code I2CMasterDecorator::readBlock(AckStatus status, uint_least8_t * data,
+                                         size_t dataLen) {
+  return i2c->readBlock(status, data, dataLen);
+}
+
+error_code I2CMasterDecorator::readPacket(uint_least8_t address,
+                                          uint_least8_t * data, size_t dataLen,
+                                          bool sendStop) {
+  return i2c->readPacket(address, data, dataLen, sendStop);
+}
+
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/I2CMasterDecorator.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,71 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_I2CMasterDecorator
+#define MaximInterface_I2CMasterDecorator
+
+#include <MaximInterface/Utilities/Export.h>
+#include "I2CMaster.hpp"
+
+namespace MaximInterface {
+
+class I2CMasterDecorator : public I2CMaster {
+protected:
+  explicit I2CMasterDecorator(I2CMaster & i2c) : i2c(&i2c) {}
+
+public:
+  void setI2CMaster(I2CMaster & i2c) { this->i2c = &i2c; }
+
+  MaximInterface_EXPORT virtual error_code start(uint_least8_t address);
+  MaximInterface_EXPORT virtual error_code stop();
+  MaximInterface_EXPORT virtual error_code writeByte(uint_least8_t data);
+  MaximInterface_EXPORT virtual error_code
+  writeBlock(const uint_least8_t * data, size_t dataLen);
+  MaximInterface_EXPORT virtual error_code
+  writePacket(uint_least8_t address, const uint_least8_t * data, size_t dataLen,
+              bool sendStop);
+  MaximInterface_EXPORT virtual error_code readByte(AckStatus status,
+                                                    uint_least8_t & data);
+  MaximInterface_EXPORT virtual error_code
+  readBlock(AckStatus status, uint_least8_t * data, size_t dataLen);
+  MaximInterface_EXPORT virtual error_code readPacket(uint_least8_t address,
+                                                      uint_least8_t * data,
+                                                      size_t dataLen,
+                                                      bool sendStop);
+
+private:
+  I2CMaster * i2c;
+};
+
+} // namespace MaximInterface
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/LoggingI2CMaster.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,141 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <utility>
+#include <MaximInterface/Utilities/HexConversions.hpp>
+#include "LoggingI2CMaster.hpp"
+
+using std::string;
+
+namespace MaximInterface {
+
+static const char startString[] = "S ";
+static const char stopString[] = "P";
+
+static string formatDataString(const uint_least8_t * data, size_t dataSize,
+                               bool read) {
+  string dataBuilder;
+  for (size_t i = 0; i < dataSize; i++) {
+    if (read) {
+      dataBuilder.append(1, '[');
+    }
+    dataBuilder.append(byteArrayToHexString(data + i, 1));
+    if (read) {
+      dataBuilder.append(1, ']');
+    }
+    dataBuilder.append(1, ' ');
+  }
+  return dataBuilder;
+}
+
+void LoggingI2CMaster::tryWriteMessage() {
+  if (writeMessage) {
+    writeMessage(messageBuilder);
+  }
+  messageBuilder.clear();
+}
+
+error_code LoggingI2CMaster::start(uint_least8_t address) {
+  messageBuilder.append(startString);
+  messageBuilder.append(formatDataString(&address, 1, false));
+  return I2CMasterDecorator::start(address);
+}
+
+error_code LoggingI2CMaster::stop() {
+  messageBuilder.append(stopString);
+  tryWriteMessage();
+  return I2CMasterDecorator::stop();
+}
+
+error_code LoggingI2CMaster::writeByte(uint_least8_t data) {
+  messageBuilder.append(formatDataString(&data, 1, false));
+  return I2CMasterDecorator::writeByte(data);
+}
+
+error_code LoggingI2CMaster::writeBlock(const uint_least8_t * data,
+                                        size_t dataLen) {
+  messageBuilder.append(formatDataString(data, dataLen, false));
+  return I2CMasterDecorator::writeBlock(data, dataLen);
+}
+
+error_code LoggingI2CMaster::writePacket(uint_least8_t address,
+                                         const uint_least8_t * data,
+                                         size_t dataLen, bool sendStop) {
+  messageBuilder.append(startString);
+  messageBuilder.append(formatDataString(&address, 1, false));
+  error_code result =
+      I2CMasterDecorator::writePacket(address, data, dataLen, sendStop);
+  if (!result) {
+    messageBuilder.append(formatDataString(data, dataLen, false));
+  }
+  if (sendStop || result) {
+    messageBuilder.append(stopString);
+    tryWriteMessage();
+  }
+  return result;
+}
+
+error_code LoggingI2CMaster::readByte(AckStatus status, uint_least8_t & data) {
+  error_code result = I2CMasterDecorator::readByte(status, data);
+  if (!result) {
+    messageBuilder.append(formatDataString(&data, 1, true));
+  }
+  return result;
+}
+
+error_code LoggingI2CMaster::readBlock(AckStatus status, uint_least8_t * data,
+                                       size_t dataLen) {
+  error_code result = I2CMasterDecorator::readBlock(status, data, dataLen);
+  if (!result) {
+    messageBuilder.append(formatDataString(data, dataLen, true));
+  }
+  return result;
+}
+
+error_code LoggingI2CMaster::readPacket(uint_least8_t address,
+                                        uint_least8_t * data, size_t dataLen,
+                                        bool sendStop) {
+  messageBuilder.append(startString);
+  messageBuilder.append(formatDataString(&address, 1, false));
+  error_code result =
+      I2CMasterDecorator::readPacket(address, data, dataLen, sendStop);
+  if (!result) {
+    messageBuilder.append(formatDataString(data, dataLen, true));
+  }
+  if (sendStop || result) {
+    messageBuilder.append(stopString);
+    tryWriteMessage();
+  }
+  return result;
+}
+
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/LoggingI2CMaster.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,79 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_LoggingI2CMaster
+#define MaximInterface_LoggingI2CMaster
+
+#include <string>
+#include <MaximInterface/Links/I2CMasterDecorator.hpp>
+#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/WriteMessage.hpp>
+
+namespace MaximInterface {
+
+class LoggingI2CMaster : public I2CMasterDecorator {
+public:
+  explicit LoggingI2CMaster(
+      I2CMaster & i2c, const WriteMessage & writeMessage = WriteMessage())
+      : I2CMasterDecorator(i2c), writeMessage(writeMessage), messageBuilder() {}
+
+  void setWriteMessage(const WriteMessage & writeMessage) {
+    this->writeMessage = writeMessage;
+  }
+
+  MaximInterface_EXPORT virtual error_code start(uint_least8_t address);
+  MaximInterface_EXPORT virtual error_code stop();
+  MaximInterface_EXPORT virtual error_code writeByte(uint_least8_t data);
+  MaximInterface_EXPORT virtual error_code
+  writeBlock(const uint_least8_t * data, size_t dataLen);
+  MaximInterface_EXPORT virtual error_code
+  writePacket(uint_least8_t address, const uint_least8_t * data, size_t dataLen,
+              bool sendStop);
+  MaximInterface_EXPORT virtual error_code readByte(AckStatus status,
+                                                    uint_least8_t & data);
+  MaximInterface_EXPORT virtual error_code
+  readBlock(AckStatus status, uint_least8_t * data, size_t dataLen);
+  MaximInterface_EXPORT virtual error_code readPacket(uint_least8_t address,
+                                                      uint_least8_t * data,
+                                                      size_t dataLen,
+                                                      bool sendStop);
+
+private:
+  void tryWriteMessage();
+
+  WriteMessage writeMessage;
+  std::string messageBuilder;
+};
+
+} // namespace MaximInterface
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/LoggingOneWireMaster.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,147 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <MaximInterface/Utilities/HexConversions.hpp>
+#include "LoggingOneWireMaster.hpp"
+
+using std::string;
+
+namespace MaximInterface {
+
+static const char strongLevelString[] = "<SP_ON>";
+
+static string formatDataString(const uint_least8_t * data, size_t dataSize,
+                               bool read) {
+  string dataBuilder;
+  for (size_t i = 0; i < dataSize; i++) {
+    if (read) {
+      dataBuilder.append(1, '[');
+    }
+    dataBuilder.append(byteArrayToHexString(data + i, 1));
+    if (read) {
+      dataBuilder.append(1, ']');
+    }
+    dataBuilder.append(1, ' ');
+  }
+  return dataBuilder;
+}
+
+void LoggingOneWireMaster::tryWriteMessage(const std::string & message) {
+  if (writeMessage) {
+    writeMessage(message);
+  }
+}
+
+error_code LoggingOneWireMaster::reset() {
+  error_code result = OneWireMasterDecorator::reset();
+  tryWriteMessage(!result ? "RP" : "RN");
+  return result;
+}
+
+error_code LoggingOneWireMaster::writeByteSetLevel(uint_least8_t sendByte,
+                                                   Level afterLevel) {
+  tryWriteMessage(formatDataString(&sendByte, 1, false));
+  if (afterLevel == StrongLevel) {
+    tryWriteMessage(strongLevelString);
+  }
+  return OneWireMasterDecorator::writeByteSetLevel(sendByte, afterLevel);
+}
+
+error_code LoggingOneWireMaster::readByteSetLevel(uint_least8_t & recvByte,
+                                                  Level afterLevel) {
+  error_code result =
+      OneWireMasterDecorator::readByteSetLevel(recvByte, afterLevel);
+  if (!result) {
+    tryWriteMessage(formatDataString(&recvByte, 1, true));
+    if (afterLevel == StrongLevel) {
+      tryWriteMessage(strongLevelString);
+    }
+  }
+  return result;
+}
+
+error_code LoggingOneWireMaster::writeBlock(const uint_least8_t * sendBuf,
+                                            size_t sendLen) {
+  tryWriteMessage(formatDataString(sendBuf, sendLen, false));
+  return OneWireMasterDecorator::writeBlock(sendBuf, sendLen);
+}
+
+error_code LoggingOneWireMaster::readBlock(uint_least8_t * recvBuf,
+                                           size_t recvLen) {
+  error_code result = OneWireMasterDecorator::readBlock(recvBuf, recvLen);
+  if (!result) {
+    tryWriteMessage(formatDataString(recvBuf, recvLen, true));
+  }
+  return result;
+}
+
+error_code LoggingOneWireMaster::setSpeed(Speed newSpeed) {
+  error_code result = OneWireMasterDecorator::setSpeed(newSpeed);
+  if (!result) {
+    string newSpeedString;
+    switch (newSpeed) {
+    case StandardSpeed:
+      newSpeedString = "<STD>";
+      break;
+
+    case OverdriveSpeed:
+      newSpeedString = "<OVR>";
+      break;
+    }
+    if (!newSpeedString.empty()) {
+      tryWriteMessage(newSpeedString);
+    }
+  }
+  return result;
+}
+
+error_code LoggingOneWireMaster::setLevel(Level newLevel) {
+  error_code result = OneWireMasterDecorator::setLevel(newLevel);
+  if (!result) {
+    string newLevelString;
+    switch (newLevel) {
+    case NormalLevel:
+      newLevelString = "<SP_OFF>";
+      break;
+
+    case StrongLevel:
+      newLevelString = strongLevelString;
+      break;
+    }
+    if (!newLevelString.empty()) {
+      tryWriteMessage(newLevelString);
+    }
+  }
+  return result;
+}
+
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/LoggingOneWireMaster.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,74 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_LoggingOneWireMaster
+#define MaximInterface_LoggingOneWireMaster
+
+#include <string>
+#include <MaximInterface/Links/OneWireMasterDecorator.hpp>
+#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/WriteMessage.hpp>
+
+namespace MaximInterface {
+
+class LoggingOneWireMaster : public OneWireMasterDecorator {
+public:
+  explicit LoggingOneWireMaster(
+      OneWireMaster & master,
+      const WriteMessage & writeMessage = WriteMessage())
+      : OneWireMasterDecorator(master), writeMessage(writeMessage) {}
+
+  void setWriteMessage(const WriteMessage & writeMessage) {
+    this->writeMessage = writeMessage;
+  }
+
+  MaximInterface_EXPORT virtual error_code reset();
+  MaximInterface_EXPORT virtual error_code
+  writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
+  MaximInterface_EXPORT virtual error_code
+  readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+  MaximInterface_EXPORT virtual error_code
+  writeBlock(const uint_least8_t * sendBuf, size_t sendLen);
+  MaximInterface_EXPORT virtual error_code readBlock(uint_least8_t * recvBuf,
+                                                     size_t recvLen);
+  MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed);
+  MaximInterface_EXPORT virtual error_code setLevel(Level newLevel);
+
+private:
+  void tryWriteMessage(const std::string & message);
+
+  WriteMessage writeMessage;
+};
+
+} // namespace MaximInterface
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/LoggingSleep.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,47 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <sstream>
+#include "LoggingSleep.hpp"
+
+namespace MaximInterface {
+
+void LoggingSleep::operator()(int ms) const {
+  if (writeMessage) {
+    std::ostringstream message;
+    message << "<DELAY" << ms << '>';
+    writeMessage(message.str());
+  }
+  SleepDecorator::operator()(ms);
+}
+
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/LoggingSleep.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,60 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_LoggingSleep
+#define MaximInterface_LoggingSleep
+
+#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/WriteMessage.hpp>
+#include "SleepDecorator.hpp"
+
+namespace MaximInterface {
+
+class LoggingSleep : public SleepDecorator {
+public:
+  LoggingSleep(const Sleep & sleep,
+               const WriteMessage & writeMessage = WriteMessage())
+      : SleepDecorator(sleep), writeMessage(writeMessage) {}
+
+  void setWriteMessage(const WriteMessage & writeMessage) {
+    this->writeMessage = writeMessage;
+  }
+
+  MaximInterface_EXPORT void operator()(int ms) const;
+
+private:
+  WriteMessage writeMessage;
+};
+
+} // namespace MaximInterface
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/OneWireMaster.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,131 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <MaximInterface/Utilities/Error.hpp>
+#include "OneWireMaster.hpp"
+
+namespace MaximInterface {
+
+error_code OneWireMaster::writeByteSetLevel(uint_least8_t sendByte,
+                                            Level afterLevel) {
+  error_code result;
+  for (int idx = 0; (idx < 8) && !result; idx++) {
+    result = writeBit(((sendByte >> idx) & 1) == 1);
+  }
+  if (!result) {
+    result = setLevel(afterLevel);
+  }
+  return result;
+}
+
+error_code OneWireMaster::readByteSetLevel(uint_least8_t & recvByte,
+                                           Level afterLevel) {
+  recvByte = 0;
+  error_code result;
+  for (int idx = 0; idx < 8; idx++) {
+    bool recvBit;
+    result = readBit(recvBit);
+    if (result) {
+      break;
+    }
+    if (recvBit) {
+      recvByte |= (1 << idx);
+    }
+  }
+  if (!result) {
+    result = setLevel(afterLevel);
+  }
+  return result;
+}
+
+error_code OneWireMaster::writeBlock(const uint_least8_t * sendBuf,
+                                     size_t sendLen) {
+  error_code result;
+  for (size_t idx = 0; (idx < sendLen) && !result; idx++) {
+    result = writeByte(sendBuf[idx]);
+  }
+  return result;
+}
+
+error_code OneWireMaster::readBlock(uint_least8_t * recvBuf, size_t recvLen) {
+  error_code result;
+  for (size_t idx = 0; (idx < recvLen) && !result; idx++) {
+    result = readByte(recvBuf[idx]);
+  }
+  return result;
+}
+
+error_code OneWireMaster::triplet(TripletData & data) {
+  error_code result = readBit(data.readBit);
+  if (!result) {
+    result = readBit(data.readBitComplement);
+  }
+  if (!result) {
+    if (data.readBit) {
+      data.writeBit = 1;
+    } else if (data.readBitComplement) {
+      data.writeBit = 0;
+    }
+    // else: use data.writeBit parameter
+    result = writeBit(data.writeBit);
+  }
+  return result;
+}
+
+const error_category & OneWireMaster::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "OneWireMaster"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case NoSlaveError:
+        return "No Slave Error";
+
+      case ShortDetectedError:
+        return "Short Detected Error";
+
+      case InvalidSpeedError:
+        return "Invalid Speed Error";
+
+      case InvalidLevelError:
+        return "Invalid Level Error";
+
+      default:
+        return defaultErrorMessage(condition);
+      }
+    }
+  } instance;
+  return instance;
+}
+
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/OneWireMaster.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,172 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_OneWireMaster
+#define MaximInterface_OneWireMaster
+
+#include <stddef.h>
+#include <stdint.h>
+#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/system_error.hpp>
+
+namespace MaximInterface {
+
+/// Base class for all 1-Wire Masters.
+class OneWireMaster {
+public:
+  /// Speed of the 1-Wire bus.
+  enum Speed { StandardSpeed = 0x00, OverdriveSpeed = 0x01 };
+
+  /// Level of the 1-Wire bus.
+  enum Level { NormalLevel = 0x00, StrongLevel = 0x02 };
+
+  /// Result of all 1-Wire commands.
+  enum ErrorValue {
+    NoSlaveError = 1, ///< Slave not detected, typically due to no presence pulse.
+    ShortDetectedError,
+    InvalidSpeedError,
+    InvalidLevelError
+  };
+
+  struct TripletData {
+    bool writeBit;
+    bool readBit;
+    bool readBitComplement;
+  };
+
+  virtual ~OneWireMaster() {}
+
+  /// Reset all of the devices on the 1-Wire bus and check for a presence pulse.
+  /// @returns NoSlaveError if reset was performed but no presence pulse was detected.
+  virtual error_code reset() = 0;
+
+  /// Send and receive one bit of communication and set a new level on the
+  /// 1-Wire bus.
+  /// @param[in,out] sendRecvBit
+  /// Input containing the bit to send and output containing the received bit.
+  /// @param afterLevel Level to set the 1-Wire bus to after communication.
+  virtual error_code touchBitSetLevel(bool & sendRecvBit, Level afterLevel) = 0;
+
+  /// Send one byte of communication and set a new level on the 1-Wire bus.
+  /// @param sendByte Byte to send on the 1-Wire bus.
+  /// @param afterLevel Level to set the 1-Wire bus to after communication.
+  MaximInterface_EXPORT virtual error_code
+  writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
+
+  /// Receive one byte of communication and set a new level on the 1-Wire bus.
+  /// @param recvByte Buffer to receive the data from the 1-Wire bus.
+  /// @param afterLevel Level to set the 1-Wire bus to after communication.
+  MaximInterface_EXPORT virtual error_code
+  readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+
+  /// Send a block of communication on the 1-Wire bus.
+  /// @param[in] sendBuf Buffer to send on the 1-Wire bus.
+  /// @param sendLen Length of the buffer to send.
+  MaximInterface_EXPORT virtual error_code
+  writeBlock(const uint_least8_t * sendBuf, size_t sendLen);
+
+  /// Receive a block of communication on the 1-Wire bus.
+  /// @param[out] recvBuf Buffer to receive the data from the 1-Wire bus.
+  /// @param recvLen Length of the buffer to receive.
+  MaximInterface_EXPORT virtual error_code readBlock(uint_least8_t * recvBuf,
+                                                     size_t recvLen);
+
+  /// Set the 1-Wire bus communication speed.
+  virtual error_code setSpeed(Speed newSpeed) = 0;
+
+  /// Set the 1-Wire bus level.
+  virtual error_code setLevel(Level newLevel) = 0;
+
+  /// 1-Wire Triplet operation.
+  /// @details Perform one bit of a 1-Wire search. This command
+  /// does two read bits and one write bit. The write bit is either
+  /// the default direction (all devices have same bit) or in case
+  /// of a discrepancy, the data.writeBit parameter is used.
+  ///@param[in,out] data
+  /// Input with desired writeBit in case both read bits are zero.
+  /// Output with all data fields set.
+  MaximInterface_EXPORT virtual error_code triplet(TripletData & data);
+
+  /// Send one bit of communication and set a new level on the 1-Wire bus.
+  /// @param sendBit Bit to send on the 1-Wire bus.
+  /// @param afterLevel Level to set the 1-Wire bus to after communication.
+  error_code writeBitSetLevel(bool sendBit, Level afterLevel) {
+    return touchBitSetLevel(sendBit, afterLevel);
+  }
+
+  /// Receive one bit of communication and set a new level on the 1-Wire bus.
+  /// @param[out] recvBit Received data from the 1-Wire bus.
+  /// @param afterLevel Level to set the 1-Wire bus to after communication.
+  error_code readBitSetLevel(bool & recvBit, Level afterLevel) {
+    recvBit = 1;
+    return touchBitSetLevel(recvBit, afterLevel);
+  }
+
+  // Alternate forms of the read and write functions.
+  error_code writeBit(bool sendBit) {
+    return writeBitSetLevel(sendBit, NormalLevel);
+  }
+  error_code readBit(bool & recvBit) {
+    return readBitSetLevel(recvBit, NormalLevel);
+  }
+  error_code writeBitPower(bool sendBit) {
+    return writeBitSetLevel(sendBit, StrongLevel);
+  }
+  error_code readBitPower(bool & recvBit) {
+    return readBitSetLevel(recvBit, StrongLevel);
+  }
+  error_code writeByte(uint_least8_t sendByte) {
+    return writeByteSetLevel(sendByte, NormalLevel);
+  }
+  error_code readByte(uint_least8_t & recvByte) {
+    return readByteSetLevel(recvByte, NormalLevel);
+  }
+  error_code writeBytePower(uint_least8_t sendByte) {
+    return writeByteSetLevel(sendByte, StrongLevel);
+  }
+  error_code readBytePower(uint_least8_t & recvByte) {
+    return readByteSetLevel(recvByte, StrongLevel);
+  }
+
+  MaximInterface_EXPORT static const error_category & errorCategory();
+};
+
+inline error_code make_error_code(OneWireMaster::ErrorValue e) {
+  return error_code(e, OneWireMaster::errorCategory());
+}
+inline error_condition make_error_condition(OneWireMaster::ErrorValue e) {
+  return error_condition(e, OneWireMaster::errorCategory());
+}
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/OneWireMasterDecorator.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,76 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include "OneWireMasterDecorator.hpp"
+
+namespace MaximInterface {
+
+error_code OneWireMasterDecorator::reset() { return master->reset(); }
+
+error_code OneWireMasterDecorator::touchBitSetLevel(bool & sendRecvBit,
+                                                    Level afterLevel) {
+  return master->touchBitSetLevel(sendRecvBit, afterLevel);
+}
+
+error_code OneWireMasterDecorator::writeByteSetLevel(uint_least8_t sendByte,
+                                                     Level afterLevel) {
+  return master->writeByteSetLevel(sendByte, afterLevel);
+}
+
+error_code OneWireMasterDecorator::readByteSetLevel(uint_least8_t & recvByte,
+                                                    Level afterLevel) {
+  return master->readByteSetLevel(recvByte, afterLevel);
+}
+
+error_code OneWireMasterDecorator::writeBlock(const uint_least8_t * sendBuf,
+                                              size_t sendLen) {
+  return master->writeBlock(sendBuf, sendLen);
+}
+
+error_code OneWireMasterDecorator::readBlock(uint_least8_t * recvBuf,
+                                             size_t recvLen) {
+  return master->readBlock(recvBuf, recvLen);
+}
+
+error_code OneWireMasterDecorator::setSpeed(Speed newSpeed) {
+  return master->setSpeed(newSpeed);
+}
+
+error_code OneWireMasterDecorator::setLevel(Level newLevel) {
+  return master->setLevel(newLevel);
+}
+
+error_code OneWireMasterDecorator::triplet(TripletData & data) {
+  return master->triplet(data);
+}
+
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/OneWireMasterDecorator.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,69 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_OneWireMasterDecorator
+#define MaximInterface_OneWireMasterDecorator
+
+#include <MaximInterface/Utilities/Export.h>
+#include "OneWireMaster.hpp"
+
+namespace MaximInterface {
+
+class OneWireMasterDecorator : public OneWireMaster {
+protected:
+  explicit OneWireMasterDecorator(OneWireMaster & master) : master(&master) {}
+
+public:
+  void setOneWireMaster(OneWireMaster & master) { this->master = &master; }
+
+  MaximInterface_EXPORT virtual error_code reset();
+  MaximInterface_EXPORT virtual error_code touchBitSetLevel(bool & sendRecvBit,
+                                                            Level afterLevel);
+  MaximInterface_EXPORT virtual error_code
+  writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
+  MaximInterface_EXPORT virtual error_code
+  readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+  MaximInterface_EXPORT virtual error_code
+  writeBlock(const uint_least8_t * sendBuf, size_t sendLen);
+  MaximInterface_EXPORT virtual error_code readBlock(uint_least8_t * recvBuf,
+                                                     size_t recvLen);
+  MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed);
+  MaximInterface_EXPORT virtual error_code setLevel(Level newLevel);
+  MaximInterface_EXPORT virtual error_code triplet(TripletData & data);
+
+private:
+  OneWireMaster * master;
+};
+
+} // namespace MaximInterface
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/RomCommands.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,222 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <algorithm>
+#include "RomCommands.hpp"
+
+namespace MaximInterface {
+
+enum RomCmd {
+  ReadRomCmd = 0x33,
+  MatchRomCmd = 0x55,
+  SearchRomCmd = 0xF0,
+  SkipRomCmd = 0xCC,
+  ResumeRomCmd = 0xA5,
+  OverdriveSkipRomCmd = 0x3C,
+  OverdriveMatchRomCmd = 0x69
+};
+
+void skipCurrentFamily(SearchRomState & searchState) {
+  // set the Last discrepancy to last family discrepancy
+  searchState.lastDiscrepancy = searchState.lastFamilyDiscrepancy;
+
+  // clear the last family discrepancy
+  searchState.lastFamilyDiscrepancy = 0;
+
+  // check for end of list
+  if (searchState.lastDiscrepancy == 0) {
+    searchState.lastDevice = true;
+  }
+}
+
+error_code verifyRom(OneWireMaster & master, const RomId & romId) {
+  SearchRomState searchState(romId);
+  error_code result = searchRom(master, searchState);
+  if (!result) {
+    // check if same device found
+    if (romId != searchState.romId) {
+      result = make_error_code(OneWireMaster::NoSlaveError);
+    }
+  }
+  return result;
+}
+
+error_code readRom(OneWireMaster & master, RomId & romId) {
+  error_code result = master.reset();
+  if (!result) {
+    result = master.writeByte(ReadRomCmd);
+  }
+
+  // read the ROM
+  RomId readId;
+  if (!result) {
+    result = master.readBlock(readId.data(), readId.size());
+  }
+
+  // verify CRC8
+  if (!result) {
+    if (valid(readId)) {
+      romId = readId;
+    } else {
+      result = make_error_code(OneWireMaster::NoSlaveError);
+    }
+  }
+
+  return result;
+}
+
+error_code skipRom(OneWireMaster & master) {
+  error_code result = master.reset();
+  if (!result) {
+    result = master.writeByte(SkipRomCmd);
+  }
+  return result;
+}
+
+error_code matchRom(OneWireMaster & master, const RomId & romId) {
+  // use MatchROM
+  error_code result = master.reset();
+  if (!result) {
+    uint_least8_t buf[1 + RomId::csize];
+    buf[0] = MatchRomCmd;
+    std::copy(romId.begin(), romId.end(), buf + 1);
+    // send command and rom
+    result = master.writeBlock(buf, sizeof(buf) / sizeof(buf[0]));
+  }
+  return result;
+}
+
+error_code overdriveSkipRom(OneWireMaster & master) {
+  error_code result = master.setSpeed(OneWireMaster::StandardSpeed);
+
+  if (!result) {
+    result = master.reset();
+  }
+
+  if (!result) {
+    result = master.writeByte(OverdriveSkipRomCmd);
+  }
+
+  if (!result) {
+    result = master.setSpeed(OneWireMaster::OverdriveSpeed);
+  }
+
+  return result;
+}
+
+error_code overdriveMatchRom(OneWireMaster & master, const RomId & romId) {
+  // use overdrive MatchROM
+  master.setSpeed(OneWireMaster::StandardSpeed);
+
+  error_code result = master.reset();
+  if (!result) {
+    result = master.writeByte(OverdriveMatchRomCmd);
+    if (!result) {
+      master.setSpeed(OneWireMaster::OverdriveSpeed);
+      // send ROM
+      result = master.writeBlock(romId.data(), romId.size());
+    }
+  }
+  return result;
+}
+
+error_code resumeRom(OneWireMaster & master) {
+  error_code result = master.reset();
+  if (!result) {
+    result = master.writeByte(ResumeRomCmd);
+  }
+  return result;
+}
+
+error_code searchRom(OneWireMaster & master, SearchRomState & searchState) {
+  if (searchState.lastDevice) {
+    searchState = SearchRomState();
+  }
+
+  error_code result = master.reset();
+  if (result) {
+    return result;
+  }
+  result = master.writeByte(SearchRomCmd);
+  if (result) {
+    return result;
+  }
+
+  SearchRomState newSearchState = searchState;
+  for (int idBitNumber = 1; idBitNumber <= 64; idBitNumber++) {
+    const int idByteNumber = (idBitNumber - 1) / 8;
+    const unsigned int idBitMask = 1 << ((idBitNumber - 1) % 8);
+
+    OneWireMaster::TripletData tripletData;
+    if (idBitNumber == newSearchState.lastDiscrepancy) {
+      tripletData.writeBit = 1;
+    } else if (idBitNumber > newSearchState.lastDiscrepancy) {
+      tripletData.writeBit = 0;
+    } else // idBitNumber < searchState.lastDiscrepancy
+    {
+      tripletData.writeBit =
+          (newSearchState.romId[idByteNumber] & idBitMask) == idBitMask;
+    }
+
+    result = master.triplet(tripletData);
+    if (result) {
+      return result;
+    }
+    if (tripletData.readBit && tripletData.readBitComplement) {
+      return make_error_code(OneWireMaster::NoSlaveError);
+    }
+
+    if (tripletData.writeBit) {
+      newSearchState.romId[idByteNumber] |= idBitMask;
+    } else {
+      newSearchState.romId[idByteNumber] &= ~idBitMask;
+      if (!tripletData.readBit && !tripletData.readBitComplement) {
+        newSearchState.lastDiscrepancy = idBitNumber;
+        if (idBitNumber <= 8) {
+          newSearchState.lastFamilyDiscrepancy = idBitNumber;
+        }
+      }
+    }
+  }
+
+  if (valid(newSearchState.romId)) {
+    if (newSearchState.lastDiscrepancy == searchState.lastDiscrepancy) {
+      newSearchState.lastDevice = true;
+    }
+    searchState = newSearchState;
+  } else {
+    result = make_error_code(OneWireMaster::NoSlaveError);
+  }
+  return result;
+}
+
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/RomCommands.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,121 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+/// @file ROM Commands for enumerating and selecting 1-Wire devices.
+
+#ifndef MaximInterface_RomCommands
+#define MaximInterface_RomCommands
+
+#include <stdint.h>
+#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/RomId.hpp>
+#include "OneWireMaster.hpp"
+
+namespace MaximInterface {
+
+/// State used by Search ROM command.
+struct SearchRomState {
+  RomId romId;
+  int_least8_t lastDiscrepancy;
+  int_least8_t lastFamilyDiscrepancy;
+  bool lastDevice;
+
+  SearchRomState()
+      : romId(), lastDiscrepancy(0), lastFamilyDiscrepancy(0),
+        lastDevice(false) {}
+    
+  explicit SearchRomState(const RomId & romId)
+      : romId(romId), lastDiscrepancy(64), lastFamilyDiscrepancy(0),
+        lastDevice(false) {}
+      
+  explicit SearchRomState(RomId::value_type familyCode)
+      : romId(), lastDiscrepancy(64), lastFamilyDiscrepancy(0),
+        lastDevice(false) {
+    setFamilyCode(romId, familyCode);
+  }
+};
+
+/// Set the search state to skip the current device family on the next
+/// Search ROM command.
+MaximInterface_EXPORT void skipCurrentFamily(SearchRomState & searchState);
+
+/// Verify that the device with the specified ROM ID is present.
+MaximInterface_EXPORT error_code verifyRom(OneWireMaster & master,
+                                           const RomId & romId);
+
+/// Use Read ROM command to read ROM ID from device on bus.
+/// @note Only use this command with a single drop bus, data
+///       collisions will occur if more than 1 device on bus.
+/// @param[out] romId ROM ID read from device.
+MaximInterface_EXPORT error_code readRom(OneWireMaster & master, RomId & romId);
+
+/// Issue Skip ROM command on bus.
+/// @note Only use this command with a single drop bus, data
+///       collisions will occur if more than 1 device on bus.
+MaximInterface_EXPORT error_code skipRom(OneWireMaster & master);
+
+/// Use the Match ROM command to select the device by its known ID.
+/// @note This command causes all devices supporting Overdrive
+///       mode to switch to Overdrive timing.
+/// @param[in] romId ROM ID of device to select.
+MaximInterface_EXPORT error_code matchRom(OneWireMaster & master,
+                                          const RomId & romId);
+
+/// Issue Overdrive Skip ROM command on bus.
+/// @note This command causes all devices supporting Overdrive
+///       mode to switch to Overdrive timing.
+/// @note Only use this command with a single drop bus, data
+///       collisions will occur if more than 1 device on bus.
+MaximInterface_EXPORT error_code overdriveSkipRom(OneWireMaster & master);
+
+/// Use the Overdrive Match ROM command to select the device by its known ID.
+/// @param[in] romId ROM ID of device to select.
+MaximInterface_EXPORT error_code overdriveMatchRom(OneWireMaster & master,
+                                                   const RomId & romId);
+
+/// Perform a Resume ROM command on bus.
+/// @details Resumes communication with the last device selected
+///          though a Match ROM or Search ROM operation.
+MaximInterface_EXPORT error_code resumeRom(OneWireMaster & master);
+
+/// Find device on the 1-Wire bus.
+/// @details
+/// This command uses the Search ROM command to enumerate all 1-Wire devices in
+/// sequence. Begin with a new search state and continue using the same search
+/// state until the last device flag is set which indicates that all devices
+/// have been discovered.
+MaximInterface_EXPORT error_code searchRom(OneWireMaster & master,
+                                           SearchRomState & searchState);
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/SelectRom.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,52 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include "SelectRom.hpp"
+
+namespace MaximInterface {
+
+error_code SelectMatchRom::operator()(OneWireMaster & master) const {
+  return matchRom(master, romId_);
+}
+
+error_code SelectMatchRomWithResume::operator()(OneWireMaster & master) const {
+  error_code result;
+  if (romId_ == data->lastRom) {
+    result = resumeRom(master);
+  } else {
+    result = matchRom(master, romId_);
+    data->lastRom = romId_;
+  }
+  return result;
+}
+
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/SelectRom.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,93 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_SelectRom
+#define MaximInterface_SelectRom
+
+#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/Function.hpp>
+#include <MaximInterface/Utilities/RomId.hpp>
+#include <MaximInterface/Utilities/system_error.hpp>
+#include "RomCommands.hpp"
+
+namespace MaximInterface {
+
+class OneWireMaster;
+
+typedef Function<error_code(OneWireMaster &)> SelectRom;
+
+/// Selector for a multidrop 1-Wire bus.
+class SelectMatchRom {
+public:
+  typedef SelectRom::argument_type argument_type;
+  typedef SelectRom::result_type result_type;
+
+  explicit SelectMatchRom(const RomId & romId = RomId()) : romId_(romId) {}
+
+  const RomId & romId() const { return romId_; }
+  void setRomId(const RomId & romId) { romId_ = romId; }
+
+  MaximInterface_EXPORT error_code operator()(OneWireMaster & master) const;
+
+private:
+  RomId romId_;
+};
+
+/// Selector for a multidrop 1-Wire bus where slaves support the Resume ROM command.
+class SelectMatchRomWithResume {
+public:
+  typedef SelectRom::argument_type argument_type;
+  typedef SelectRom::result_type result_type;
+
+  struct SharedData {
+    RomId lastRom;
+
+    SharedData() : lastRom() {}
+  };
+
+  explicit SelectMatchRomWithResume(SharedData & data,
+                                    const RomId & romId = RomId())
+      : romId_(romId), data(&data) {}
+
+  const RomId & romId() const { return romId_; }
+  void setRomId(const RomId & romId) { romId_ = romId; }
+
+  MaximInterface_EXPORT error_code operator()(OneWireMaster & master) const;
+
+private:
+  RomId romId_;
+  SharedData * data;
+};
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/Sleep.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,47 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_Sleep
+#define MaximInterface_Sleep
+
+namespace MaximInterface {
+
+class Sleep {
+public:
+  virtual ~Sleep() {}
+
+  virtual void operator()(int ms) const = 0;
+};
+
+} // namespace MaximInterface
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/SleepDecorator.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,39 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include "SleepDecorator.hpp"
+
+namespace MaximInterface {
+
+void SleepDecorator::operator()(int ms) const { (*sleep)(ms); }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/SleepDecorator.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,55 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_SleepDecorator
+#define MaximInterface_SleepDecorator
+
+#include <MaximInterface/Utilities/Export.h>
+#include "Sleep.hpp"
+
+namespace MaximInterface {
+
+class SleepDecorator : public Sleep {
+protected:
+  explicit SleepDecorator(const Sleep & sleep) : sleep(&sleep) {}
+
+public:
+  void setSleep(const Sleep & sleep) { this->sleep = &sleep; }
+  MaximInterface_EXPORT virtual void operator()(int ms) const;
+
+private:
+  const Sleep * sleep;
+};
+
+} // namespace MaximInterface
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/Uart.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,75 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <MaximInterface/Utilities/Error.hpp>
+#include "Uart.hpp"
+
+namespace MaximInterface {
+
+error_code Uart::writeBlock(const uint_least8_t * data, size_t dataLen) {
+  error_code result;
+  for (size_t i = 0; i < dataLen && !result; i++) {
+    result = writeByte(data[i]);
+  }
+  return result;
+}
+
+error_code Uart::readBlock(uint_least8_t * data, size_t dataLen) {
+  error_code result;
+  for (size_t i = 0; i < dataLen && !result; i++) {
+    result = readByte(data[i]);
+  }
+  return result;
+}
+
+const error_category & Uart::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "UART"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case TimeoutError:
+        return "Timeout Error";
+
+      case OverrunError:
+        return "Overrun Error";
+
+      default:
+        return defaultErrorMessage(condition);
+      }
+    }
+  } instance;
+  return instance;
+}
+
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Links/Uart.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,75 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_Uart
+#define MaximInterface_Uart
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/system_error.hpp>
+
+namespace MaximInterface {
+
+class Uart {
+public:
+  enum ErrorValue {
+    TimeoutError = 1, ///< Read operation aborted due to timeout.
+    OverrunError      ///< Received data lost due to read buffer overrun.
+  };
+
+  virtual ~Uart() {}
+
+  virtual error_code setBaud(int_least32_t baud) = 0;
+  virtual error_code sendBreak() = 0;
+  virtual error_code clearReadBuffer() = 0;
+  virtual error_code writeByte(uint_least8_t data) = 0;
+  MaximInterface_EXPORT virtual error_code
+  writeBlock(const uint_least8_t * data, size_t dataLen);
+  virtual error_code readByte(uint_least8_t & data) = 0;
+  MaximInterface_EXPORT virtual error_code readBlock(uint_least8_t * data,
+                                                     size_t dataLen);
+
+  MaximInterface_EXPORT static const error_category & errorCategory();
+};
+
+inline error_code make_error_code(Uart::ErrorValue e) {
+  return error_code(e, Uart::errorCategory());
+}
+inline error_condition make_error_condition(Uart::ErrorValue e) {
+  return error_condition(e, Uart::errorCategory());
+}
+
+} // namespace MaximInterface
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterface.vcxproj	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,254 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{7E1C5898-64B8-422F-8030-F8D2EFB5B0CB}</ProjectGuid>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <Keyword>ManagedCProj</Keyword>
+    <RootNamespace>MaximInterface</RootNamespace>
+    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <CLRSupport>true</CLRSupport>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <CLRSupport>true</CLRSupport>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <CLRSupport>true</CLRSupport>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v140</PlatformToolset>
+    <CLRSupport>true</CLRSupport>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <IncludePath>$(ProjectDir)\..;$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <IncludePath>$(ProjectDir)\..;$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <IncludePath>$(ProjectDir)\..;$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <IncludePath>$(ProjectDir)\..;$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>NOMINMAX;WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies />
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>NOMINMAX;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies />
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PreprocessorDefinitions>NOMINMAX;WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies />
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PreprocessorDefinitions>NOMINMAX;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies />
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <Reference Include="OneWireLinkLayer">
+      <HintPath>Platforms\dotnet\OneWireLinkLayer\OneWireLinkLayer.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="Devices\DS18B20.cpp" />
+    <ClCompile Include="Devices\DS1920.cpp" />
+    <ClCompile Include="Devices\DS2413.cpp" />
+    <ClCompile Include="Devices\DS2431.cpp" />
+    <ClCompile Include="Devices\DS2465.cpp" />
+    <ClCompile Include="Devices\DS2480B.cpp" />
+    <ClCompile Include="Devices\DS2482_DS2484.cpp" />
+    <ClCompile Include="Devices\DS28C36_DS2476.cpp" />
+    <ClCompile Include="Devices\DS28E15_22_25.cpp" />
+    <ClCompile Include="Devices\DS28E17.cpp" />
+    <ClCompile Include="Devices\DS28E38.cpp" />
+    <ClCompile Include="Devices\DS9400.cpp" />
+    <ClCompile Include="Links\I2CMaster.cpp" />
+    <ClCompile Include="Links\I2CMasterDecorator.cpp" />
+    <ClCompile Include="Links\LoggingI2CMaster.cpp" />
+    <ClCompile Include="Links\LoggingOneWireMaster.cpp" />
+    <ClCompile Include="Links\OneWireMaster.cpp" />
+    <ClCompile Include="Links\OneWireMasterDecorator.cpp" />
+    <ClCompile Include="Links\RomCommands.cpp" />
+    <ClCompile Include="Links\SelectRom.cpp" />
+    <ClCompile Include="Links\LoggingSleep.cpp" />
+    <ClCompile Include="Links\SleepDecorator.cpp" />
+    <ClCompile Include="Links\Uart.cpp" />
+    <ClCompile Include="Platforms\dotnet\DS9481P_300.cpp">
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)dotnet\</ObjectFileName>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)dotnet\</ObjectFileName>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)dotnet\</ObjectFileName>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)dotnet\</ObjectFileName>
+    </ClCompile>
+    <ClCompile Include="Platforms\dotnet\OneWireLinkLayerMaster.cpp">
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)dotnet\</ObjectFileName>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)dotnet\</ObjectFileName>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)dotnet\</ObjectFileName>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)dotnet\</ObjectFileName>
+    </ClCompile>
+    <ClCompile Include="Platforms\dotnet\Sleep.cpp">
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)\dotnet\</ObjectFileName>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)\dotnet\</ObjectFileName>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)\dotnet\</ObjectFileName>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)\dotnet\</ObjectFileName>
+    </ClCompile>
+    <ClCompile Include="Platforms\dotnet\Uart.cpp">
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)\dotnet\</ObjectFileName>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)\dotnet\</ObjectFileName>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)\dotnet\</ObjectFileName>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)\dotnet\</ObjectFileName>
+    </ClCompile>
+    <ClCompile Include="Utilities\crc.cpp" />
+    <ClCompile Include="Utilities\Ecc256.cpp" />
+    <ClCompile Include="Utilities\Error.cpp" />
+    <ClCompile Include="Utilities\HexConversions.cpp" />
+    <ClCompile Include="Utilities\system_error.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="Devices\DS18B20.hpp" />
+    <ClInclude Include="Devices\DS1920.hpp" />
+    <ClInclude Include="Devices\DS2413.hpp" />
+    <ClInclude Include="Devices\DS2431.hpp" />
+    <ClInclude Include="Devices\DS2465.hpp" />
+    <ClInclude Include="Devices\DS2480B.hpp" />
+    <ClInclude Include="Devices\DS2482_DS2484.hpp" />
+    <ClInclude Include="Devices\DS28C36_DS2476.hpp" />
+    <ClInclude Include="Devices\DS28E15_22_25.hpp" />
+    <ClInclude Include="Devices\DS28E17.hpp" />
+    <ClInclude Include="Devices\DS28E38.hpp" />
+    <ClInclude Include="Devices\DS9400.hpp" />
+    <ClInclude Include="Links\I2CMaster.hpp" />
+    <ClInclude Include="Links\I2CMasterDecorator.hpp" />
+    <ClInclude Include="Links\LoggingI2CMaster.hpp" />
+    <ClInclude Include="Links\LoggingOneWireMaster.hpp" />
+    <ClInclude Include="Links\OneWireMaster.hpp" />
+    <ClInclude Include="Links\OneWireMasterDecorator.hpp" />
+    <ClInclude Include="Links\RomCommands.hpp" />
+    <ClInclude Include="Links\SelectRom.hpp" />
+    <ClInclude Include="Links\LoggingSleep.hpp" />
+    <ClInclude Include="Links\Sleep.hpp" />
+    <ClInclude Include="Links\SleepDecorator.hpp" />
+    <ClInclude Include="Links\Uart.hpp" />
+    <ClInclude Include="Platforms\dotnet\ChangeSizeType.hpp" />
+    <ClInclude Include="Platforms\dotnet\DelegateWrapper.hpp" />
+    <ClInclude Include="Platforms\dotnet\DS9481P_300.hpp" />
+    <ClInclude Include="Platforms\dotnet\MoveOnly.hpp" />
+    <ClInclude Include="Platforms\dotnet\OneWireLinkLayerMaster.hpp" />
+    <ClInclude Include="Platforms\dotnet\Sleep.hpp" />
+    <ClInclude Include="Platforms\dotnet\Uart.hpp" />
+    <ClInclude Include="Utilities\array.hpp" />
+    <ClInclude Include="Utilities\crc.hpp" />
+    <ClInclude Include="Utilities\Ecc256.hpp" />
+    <ClInclude Include="Utilities\Error.hpp" />
+    <ClInclude Include="Utilities\Export.h" />
+    <ClInclude Include="Utilities\FlagSet.hpp" />
+    <ClInclude Include="Utilities\Function.hpp" />
+    <ClInclude Include="Utilities\HexConversions.hpp" />
+    <ClInclude Include="Utilities\ManId.hpp" />
+    <ClInclude Include="Utilities\RomId.hpp" />
+    <ClInclude Include="Utilities\Segment.hpp" />
+    <ClInclude Include="Utilities\Sha256.hpp" />
+    <ClInclude Include="Utilities\system_error.hpp" />
+    <ClInclude Include="Utilities\type_traits.hpp" />
+    <ClInclude Include="Utilities\Uncopyable.hpp" />
+    <ClInclude Include="Utilities\WriteMessage.hpp" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+  <Target Name="CopyOneWireLinkLayerDependenciesToOutDir" AfterTargets="Link">
+    <ItemGroup Condition="'$(Platform)'=='Win32'">
+      <Files Include="Platforms\dotnet\OneWireLinkLayer\IB*32.dll" />
+    </ItemGroup>
+    <ItemGroup Condition="'$(Platform)'=='x64'">
+      <Files Include="Platforms\dotnet\OneWireLinkLayer\IB*64.dll" />
+    </ItemGroup>
+    <Copy SourceFiles="@(Files)" DestinationFolder="$(OutDir)" SkipUnchangedFiles="true" />
+  </Target>
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterface.vcxproj.filters	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,282 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+    <Filter Include="Header Files\Platforms/dotnet">
+      <UniqueIdentifier>{20e2adae-b837-416c-9711-27583e3c230b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Platforms/dotnet">
+      <UniqueIdentifier>{63d67a30-8ace-4b0d-8f09-ca770ba4211e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Devices">
+      <UniqueIdentifier>{e279ae2d-8636-4b89-8c6c-69db07e90944}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Devices">
+      <UniqueIdentifier>{1441f2db-880a-41e6-9db3-3fcf2e082fc1}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Links">
+      <UniqueIdentifier>{63236a03-f900-4307-9ae0-db9f5ad41a32}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Utilities">
+      <UniqueIdentifier>{92539371-ab18-4bd0-b3d6-2449d18a6620}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Links">
+      <UniqueIdentifier>{bd04ab64-fd11-4c55-bada-233093987852}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Utilities">
+      <UniqueIdentifier>{017fb907-ad1f-4072-a2f1-7cd23bb1c735}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="Platforms\dotnet\DS9481P_300.cpp">
+      <Filter>Source Files\Platforms/dotnet</Filter>
+    </ClCompile>
+    <ClCompile Include="Platforms\dotnet\OneWireLinkLayerMaster.cpp">
+      <Filter>Source Files\Platforms/dotnet</Filter>
+    </ClCompile>
+    <ClCompile Include="Platforms\dotnet\Sleep.cpp">
+      <Filter>Source Files\Platforms/dotnet</Filter>
+    </ClCompile>
+    <ClCompile Include="Platforms\dotnet\Uart.cpp">
+      <Filter>Source Files\Platforms/dotnet</Filter>
+    </ClCompile>
+    <ClCompile Include="Devices\DS18B20.cpp">
+      <Filter>Source Files\Devices</Filter>
+    </ClCompile>
+    <ClCompile Include="Devices\DS28E15_22_25.cpp">
+      <Filter>Source Files\Devices</Filter>
+    </ClCompile>
+    <ClCompile Include="Devices\DS28E17.cpp">
+      <Filter>Source Files\Devices</Filter>
+    </ClCompile>
+    <ClCompile Include="Devices\DS28E38.cpp">
+      <Filter>Source Files\Devices</Filter>
+    </ClCompile>
+    <ClCompile Include="Devices\DS1920.cpp">
+      <Filter>Source Files\Devices</Filter>
+    </ClCompile>
+    <ClCompile Include="Devices\DS2413.cpp">
+      <Filter>Source Files\Devices</Filter>
+    </ClCompile>
+    <ClCompile Include="Devices\DS2431.cpp">
+      <Filter>Source Files\Devices</Filter>
+    </ClCompile>
+    <ClCompile Include="Devices\DS2465.cpp">
+      <Filter>Source Files\Devices</Filter>
+    </ClCompile>
+    <ClCompile Include="Devices\DS2480B.cpp">
+      <Filter>Source Files\Devices</Filter>
+    </ClCompile>
+    <ClCompile Include="Devices\DS9400.cpp">
+      <Filter>Source Files\Devices</Filter>
+    </ClCompile>
+    <ClCompile Include="Utilities\crc.cpp">
+      <Filter>Source Files\Utilities</Filter>
+    </ClCompile>
+    <ClCompile Include="Utilities\Ecc256.cpp">
+      <Filter>Source Files\Utilities</Filter>
+    </ClCompile>
+    <ClCompile Include="Utilities\HexConversions.cpp">
+      <Filter>Source Files\Utilities</Filter>
+    </ClCompile>
+    <ClCompile Include="Utilities\system_error.cpp">
+      <Filter>Source Files\Utilities</Filter>
+    </ClCompile>
+    <ClCompile Include="Links\I2CMaster.cpp">
+      <Filter>Source Files\Links</Filter>
+    </ClCompile>
+    <ClCompile Include="Links\I2CMasterDecorator.cpp">
+      <Filter>Source Files\Links</Filter>
+    </ClCompile>
+    <ClCompile Include="Links\LoggingI2CMaster.cpp">
+      <Filter>Source Files\Links</Filter>
+    </ClCompile>
+    <ClCompile Include="Links\LoggingOneWireMaster.cpp">
+      <Filter>Source Files\Links</Filter>
+    </ClCompile>
+    <ClCompile Include="Links\LoggingSleep.cpp">
+      <Filter>Source Files\Links</Filter>
+    </ClCompile>
+    <ClCompile Include="Links\OneWireMaster.cpp">
+      <Filter>Source Files\Links</Filter>
+    </ClCompile>
+    <ClCompile Include="Links\OneWireMasterDecorator.cpp">
+      <Filter>Source Files\Links</Filter>
+    </ClCompile>
+    <ClCompile Include="Links\RomCommands.cpp">
+      <Filter>Source Files\Links</Filter>
+    </ClCompile>
+    <ClCompile Include="Links\SelectRom.cpp">
+      <Filter>Source Files\Links</Filter>
+    </ClCompile>
+    <ClCompile Include="Links\SleepDecorator.cpp">
+      <Filter>Source Files\Links</Filter>
+    </ClCompile>
+    <ClCompile Include="Links\Uart.cpp">
+      <Filter>Source Files\Links</Filter>
+    </ClCompile>
+    <ClCompile Include="Devices\DS28C36_DS2476.cpp">
+      <Filter>Source Files\Devices</Filter>
+    </ClCompile>
+    <ClCompile Include="Devices\DS2482_DS2484.cpp">
+      <Filter>Source Files\Devices</Filter>
+    </ClCompile>
+    <ClCompile Include="Utilities\Error.cpp">
+      <Filter>Source Files\Utilities</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="Platforms\dotnet\ChangeSizeType.hpp">
+      <Filter>Header Files\Platforms/dotnet</Filter>
+    </ClInclude>
+    <ClInclude Include="Platforms\dotnet\DelegateWrapper.hpp">
+      <Filter>Header Files\Platforms/dotnet</Filter>
+    </ClInclude>
+    <ClInclude Include="Platforms\dotnet\DS9481P_300.hpp">
+      <Filter>Header Files\Platforms/dotnet</Filter>
+    </ClInclude>
+    <ClInclude Include="Platforms\dotnet\MoveOnly.hpp">
+      <Filter>Header Files\Platforms/dotnet</Filter>
+    </ClInclude>
+    <ClInclude Include="Platforms\dotnet\OneWireLinkLayerMaster.hpp">
+      <Filter>Header Files\Platforms/dotnet</Filter>
+    </ClInclude>
+    <ClInclude Include="Platforms\dotnet\Sleep.hpp">
+      <Filter>Header Files\Platforms/dotnet</Filter>
+    </ClInclude>
+    <ClInclude Include="Platforms\dotnet\Uart.hpp">
+      <Filter>Header Files\Platforms/dotnet</Filter>
+    </ClInclude>
+    <ClInclude Include="Devices\DS18B20.hpp">
+      <Filter>Header Files\Devices</Filter>
+    </ClInclude>
+    <ClInclude Include="Devices\DS28E15_22_25.hpp">
+      <Filter>Header Files\Devices</Filter>
+    </ClInclude>
+    <ClInclude Include="Devices\DS28E17.hpp">
+      <Filter>Header Files\Devices</Filter>
+    </ClInclude>
+    <ClInclude Include="Devices\DS28E38.hpp">
+      <Filter>Header Files\Devices</Filter>
+    </ClInclude>
+    <ClInclude Include="Devices\DS1920.hpp">
+      <Filter>Header Files\Devices</Filter>
+    </ClInclude>
+    <ClInclude Include="Devices\DS2413.hpp">
+      <Filter>Header Files\Devices</Filter>
+    </ClInclude>
+    <ClInclude Include="Devices\DS2431.hpp">
+      <Filter>Header Files\Devices</Filter>
+    </ClInclude>
+    <ClInclude Include="Devices\DS2465.hpp">
+      <Filter>Header Files\Devices</Filter>
+    </ClInclude>
+    <ClInclude Include="Devices\DS2480B.hpp">
+      <Filter>Header Files\Devices</Filter>
+    </ClInclude>
+    <ClInclude Include="Devices\DS9400.hpp">
+      <Filter>Header Files\Devices</Filter>
+    </ClInclude>
+    <ClInclude Include="Utilities\array.hpp">
+      <Filter>Header Files\Utilities</Filter>
+    </ClInclude>
+    <ClInclude Include="Utilities\crc.hpp">
+      <Filter>Header Files\Utilities</Filter>
+    </ClInclude>
+    <ClInclude Include="Utilities\Ecc256.hpp">
+      <Filter>Header Files\Utilities</Filter>
+    </ClInclude>
+    <ClInclude Include="Utilities\Function.hpp">
+      <Filter>Header Files\Utilities</Filter>
+    </ClInclude>
+    <ClInclude Include="Utilities\HexConversions.hpp">
+      <Filter>Header Files\Utilities</Filter>
+    </ClInclude>
+    <ClInclude Include="Utilities\ManId.hpp">
+      <Filter>Header Files\Utilities</Filter>
+    </ClInclude>
+    <ClInclude Include="Utilities\RomId.hpp">
+      <Filter>Header Files\Utilities</Filter>
+    </ClInclude>
+    <ClInclude Include="Utilities\Sha256.hpp">
+      <Filter>Header Files\Utilities</Filter>
+    </ClInclude>
+    <ClInclude Include="Utilities\system_error.hpp">
+      <Filter>Header Files\Utilities</Filter>
+    </ClInclude>
+    <ClInclude Include="Utilities\type_traits.hpp">
+      <Filter>Header Files\Utilities</Filter>
+    </ClInclude>
+    <ClInclude Include="Utilities\Uncopyable.hpp">
+      <Filter>Header Files\Utilities</Filter>
+    </ClInclude>
+    <ClInclude Include="Utilities\WriteMessage.hpp">
+      <Filter>Header Files\Utilities</Filter>
+    </ClInclude>
+    <ClInclude Include="Links\I2CMaster.hpp">
+      <Filter>Header Files\Links</Filter>
+    </ClInclude>
+    <ClInclude Include="Links\I2CMasterDecorator.hpp">
+      <Filter>Header Files\Links</Filter>
+    </ClInclude>
+    <ClInclude Include="Links\LoggingI2CMaster.hpp">
+      <Filter>Header Files\Links</Filter>
+    </ClInclude>
+    <ClInclude Include="Links\LoggingOneWireMaster.hpp">
+      <Filter>Header Files\Links</Filter>
+    </ClInclude>
+    <ClInclude Include="Links\LoggingSleep.hpp">
+      <Filter>Header Files\Links</Filter>
+    </ClInclude>
+    <ClInclude Include="Links\OneWireMaster.hpp">
+      <Filter>Header Files\Links</Filter>
+    </ClInclude>
+    <ClInclude Include="Links\OneWireMasterDecorator.hpp">
+      <Filter>Header Files\Links</Filter>
+    </ClInclude>
+    <ClInclude Include="Links\RomCommands.hpp">
+      <Filter>Header Files\Links</Filter>
+    </ClInclude>
+    <ClInclude Include="Links\SelectRom.hpp">
+      <Filter>Header Files\Links</Filter>
+    </ClInclude>
+    <ClInclude Include="Links\Sleep.hpp">
+      <Filter>Header Files\Links</Filter>
+    </ClInclude>
+    <ClInclude Include="Links\SleepDecorator.hpp">
+      <Filter>Header Files\Links</Filter>
+    </ClInclude>
+    <ClInclude Include="Links\Uart.hpp">
+      <Filter>Header Files\Links</Filter>
+    </ClInclude>
+    <ClInclude Include="Devices\DS28C36_DS2476.hpp">
+      <Filter>Header Files\Devices</Filter>
+    </ClInclude>
+    <ClInclude Include="Devices\DS2482_DS2484.hpp">
+      <Filter>Header Files\Devices</Filter>
+    </ClInclude>
+    <ClInclude Include="Utilities\FlagSet.hpp">
+      <Filter>Header Files\Utilities</Filter>
+    </ClInclude>
+    <ClInclude Include="Utilities\Error.hpp">
+      <Filter>Header Files\Utilities</Filter>
+    </ClInclude>
+    <ClInclude Include="Utilities\Export.h">
+      <Filter>Header Files\Utilities</Filter>
+    </ClInclude>
+    <ClInclude Include="Utilities\Segment.hpp">
+      <Filter>Header Files\Utilities</Filter>
+    </ClInclude>
+  </ItemGroup>
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/dotnet/.mbedignore	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,1 @@
+*
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/dotnet/ChangeSizeType.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,63 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#pragma once
+
+#include <algorithm>
+#include <limits>
+#include <type_traits>
+
+namespace MaximInterface {
+
+/// Adapts functions taking a data pointer and data size where the size type is
+/// not size_t. The function will be called multiple times if necessary to
+/// process all data.
+template <typename NewSize, typename Func, typename Data>
+void changeSizeType(Func func, Data data, size_t dataSize) {
+  using namespace std;
+
+  // Check if NewSize can represent the maximum value of dataSize.
+  if (numeric_limits<decltype(dataSize)>::max() >
+      static_cast<make_unsigned_t<NewSize>>(numeric_limits<NewSize>::max())) {
+    do {
+      const auto chunkSize =
+          min<decltype(dataSize)>(dataSize, numeric_limits<NewSize>::max());
+      func(data, static_cast<NewSize>(chunkSize));
+      data += chunkSize;
+      dataSize -= chunkSize;
+    } while (dataSize > 0);
+  } else {
+    func(data, static_cast<NewSize>(dataSize));
+  }
+}
+
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/dotnet/DS9481P_300.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,283 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <utility>
+#include <msclr/marshal_cppstd.h>
+#include <MaximInterface/Utilities/Error.hpp>
+#include "DS9481P_300.hpp"
+
+using System::IO::Ports::SerialPort;
+using msclr::interop::marshal_as;
+using std::string;
+
+namespace MaximInterface {
+
+DS9481P_300::DS9481P_300()
+    : currentBus(Bus::None), linkLayerMaster("{DS9097U_DS9480}"),
+      oneWireMaster_(*this), serial(), ds9400(serial), i2cMaster_(*this) {}
+
+DS9481P_300::~DS9481P_300() { disconnect(); }
+
+error_code DS9481P_300::connect(const string & portName) {
+  return connected() ? make_error_code(ConnectionStateError)
+                     : selectBus(Bus::OneWire, portName);
+}
+
+void DS9481P_300::disconnect() { selectBus(Bus::None); }
+
+string DS9481P_300::portName() const {
+  switch (currentBus) {
+  case Bus::I2C:
+    return serial.portName();
+
+  case Bus::OneWire:
+    return linkLayerMaster.portName();
+  }
+  return "";
+}
+
+error_code DS9481P_300::selectBus(Bus newBus) {
+  return connected() ? selectBus(newBus, portName())
+                     : make_error_code(ConnectionStateError);
+}
+
+error_code DS9481P_300::selectBus(Bus newBus, const string & portName) {
+  error_code result;
+  if (currentBus != newBus) {
+    const auto selectI2C = [this](const string & portName) {
+      auto result = serial.connect(portName);
+      if (!result) {
+        // Escape DS2480 Mode.
+        result = serial.writeByte(0xE5);
+      }
+	  if (!result) {
+	    // Wait for awake notification.
+		uint_least8_t data;
+		result = serial.readByte(data);
+	  }
+      return result;
+    };
+
+    const auto selectOneWire = [this](const string & portName) {
+      return linkLayerMaster.connect(portName);
+    };
+
+    switch (currentBus) {
+    case Bus::None:
+      switch (newBus) {
+      case Bus::OneWire:
+        result = selectOneWire(portName);
+        break;
+
+      case Bus::I2C:
+        result = selectI2C(portName);
+        break;
+      }
+      break;
+
+    case Bus::OneWire:
+      linkLayerMaster.disconnect();
+      switch (newBus) {
+      case Bus::I2C:
+        result = selectI2C(portName);
+        break;
+      }
+      break;
+
+    case Bus::I2C: {
+      constexpr uint_least8_t buffer[] = {'C', 'O'};
+      result = serial.writeBlock(buffer, sizeof(buffer) / sizeof(buffer[0]));
+      if (!result) {
+        serial.disconnect();
+        switch (newBus) {
+        case Bus::OneWire:
+          result = selectOneWire(portName);
+          break;
+        }
+      }
+    } break;
+    }
+    if (!result) {
+      currentBus = newBus;
+    }
+  }
+  return result;
+}
+
+error_code DS9481P_300::OneWireMasterImpl::reset() {
+  return selectAndExecute([this] { return OneWireMasterDecorator::reset(); });
+}
+
+error_code DS9481P_300::OneWireMasterImpl::touchBitSetLevel(bool & sendRecvBit,
+                                                            Level afterLevel) {
+  return selectAndExecute([this, &sendRecvBit, afterLevel] {
+    return OneWireMasterDecorator::touchBitSetLevel(sendRecvBit, afterLevel);
+  });
+}
+
+error_code
+DS9481P_300::OneWireMasterImpl::writeByteSetLevel(uint_least8_t sendByte,
+                                                  Level afterLevel) {
+  return selectAndExecute([this, sendByte, afterLevel] {
+    return OneWireMasterDecorator::writeByteSetLevel(sendByte, afterLevel);
+  });
+}
+
+error_code
+DS9481P_300::OneWireMasterImpl::readByteSetLevel(uint_least8_t & recvByte,
+                                                 Level afterLevel) {
+  return selectAndExecute([this, &recvByte, afterLevel] {
+    return OneWireMasterDecorator::readByteSetLevel(recvByte, afterLevel);
+  });
+}
+
+error_code
+DS9481P_300::OneWireMasterImpl::writeBlock(const uint_least8_t * sendBuf,
+                                           size_t sendLen) {
+  return selectAndExecute([this, sendBuf, sendLen] {
+    return OneWireMasterDecorator::writeBlock(sendBuf, sendLen);
+  });
+}
+
+error_code DS9481P_300::OneWireMasterImpl::readBlock(uint_least8_t * recvBuf,
+                                                     size_t recvLen) {
+  return selectAndExecute([this, recvBuf, recvLen] {
+    return OneWireMasterDecorator::readBlock(recvBuf, recvLen);
+  });
+}
+
+error_code DS9481P_300::OneWireMasterImpl::setSpeed(Speed newSpeed) {
+  return selectAndExecute(
+      [this, newSpeed] { return OneWireMasterDecorator::setSpeed(newSpeed); });
+}
+
+error_code DS9481P_300::OneWireMasterImpl::setLevel(Level newLevel) {
+  return selectAndExecute(
+      [this, newLevel] { return OneWireMasterDecorator::setLevel(newLevel); });
+}
+
+error_code DS9481P_300::OneWireMasterImpl::triplet(TripletData & data) {
+  return selectAndExecute(
+      [this, &data] { return OneWireMasterDecorator::triplet(data); });
+}
+
+template <typename Func>
+error_code DS9481P_300::OneWireMasterImpl::selectAndExecute(Func operation) {
+  auto result = parent->selectBus(Bus::OneWire);
+  if (!result) {
+    result = operation();
+  }
+  return result;
+}
+
+error_code DS9481P_300::I2CMasterImpl::start(uint_least8_t address) {
+  return selectAndExecute(
+      [this, address] { return I2CMasterDecorator::start(address); });
+}
+
+error_code DS9481P_300::I2CMasterImpl::stop() {
+  return selectAndExecute([this] { return I2CMasterDecorator::stop(); });
+}
+
+error_code DS9481P_300::I2CMasterImpl::writeByte(uint_least8_t data) {
+  return selectAndExecute(
+      [this, data] { return I2CMasterDecorator::writeByte(data); });
+}
+
+error_code DS9481P_300::I2CMasterImpl::writeBlock(const uint_least8_t * data,
+                                                  size_t dataLen) {
+  return selectAndExecute([this, data, dataLen] {
+    return I2CMasterDecorator::writeBlock(data, dataLen);
+  });
+}
+
+error_code DS9481P_300::I2CMasterImpl::writePacket(uint_least8_t address,
+                                                   const uint_least8_t * data,
+                                                   size_t dataLen,
+                                                   bool sendStop) {
+  return selectAndExecute([this, address, data, dataLen, sendStop] {
+    return I2CMasterDecorator::writePacket(address, data, dataLen, sendStop);
+  });
+}
+
+error_code DS9481P_300::I2CMasterImpl::readByte(AckStatus status,
+                                                uint_least8_t & data) {
+  return selectAndExecute([this, status, &data] {
+    return I2CMasterDecorator::readByte(status, data);
+  });
+}
+
+error_code DS9481P_300::I2CMasterImpl::readBlock(AckStatus status,
+                                                 uint_least8_t * data,
+                                                 size_t dataLen) {
+  return selectAndExecute([this, status, data, dataLen] {
+    return I2CMasterDecorator::readBlock(status, data, dataLen);
+  });
+}
+
+error_code DS9481P_300::I2CMasterImpl::readPacket(uint_least8_t address,
+                                                  uint_least8_t * data,
+                                                  size_t dataLen,
+                                                  bool sendStop) {
+  return selectAndExecute([this, address, data, dataLen, sendStop] {
+    return I2CMasterDecorator::readPacket(address, data, dataLen, sendStop);
+  });
+}
+
+template <typename Func>
+error_code DS9481P_300::I2CMasterImpl::selectAndExecute(Func operation) {
+  auto result = parent->selectBus(Bus::I2C);
+  if (!result) {
+    result = operation();
+  }
+  return result;
+}
+
+const error_category & DS9481P_300::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "DS9481P_300"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case ConnectionStateError:
+        return "Connection State Error";
+
+      default:
+        return defaultErrorMessage(condition);
+      }
+    }
+  } instance;
+  return instance;
+}
+
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/dotnet/DS9481P_300.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,148 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#pragma once
+
+#include <string>
+#include <MaximInterface/Devices/DS9400.hpp>
+#include <MaximInterface/Links/I2CMasterDecorator.hpp>
+#include <MaximInterface/Links/OneWireMasterDecorator.hpp>
+#include <MaximInterface/Utilities/Export.h>
+#include "MoveOnly.hpp"
+#include "OneWireLinkLayerMaster.hpp"
+#include "Uart.hpp"
+
+namespace MaximInterface {
+
+/// DS9481P-300 USB to 1-Wire and I2C adapter.
+class DS9481P_300 : private MoveOnly {
+public:
+  enum ErrorValue { ConnectionStateError = 1 };
+
+  MaximInterface_EXPORT DS9481P_300();
+  MaximInterface_EXPORT ~DS9481P_300();
+
+  DS9481P_300(DS9481P_300 &&) = default;
+  DS9481P_300 & operator=(DS9481P_300 &&) = default;
+
+  /// Access the 1-Wire master when connected to an adapter.
+  OneWireMaster & oneWireMaster() { return oneWireMaster_; }
+  
+  /// Access the I2C master when connected to an adapter.
+  I2CMaster & i2cMaster() { return i2cMaster_; }
+
+  /// Connect to an adapter on the specified COM port.
+  MaximInterface_EXPORT error_code connect(const std::string & portName);
+  
+  /// Disconnect from the adapter on the current COM port.
+  MaximInterface_EXPORT void disconnect();
+
+  /// Check if currently connected to an adapter.
+  /// @returns True if connected.
+  bool connected() const { return currentBus != Bus::None; }
+  
+  /// Get the currently connected COM port name.
+  MaximInterface_EXPORT std::string portName() const;
+
+  MaximInterface_EXPORT static const error_category & errorCategory();
+
+private:
+  class OneWireMasterImpl : public OneWireMasterDecorator {
+  public:
+    explicit OneWireMasterImpl(DS9481P_300 & parent)
+        : OneWireMasterDecorator(parent.linkLayerMaster), parent(&parent) {}
+
+    virtual error_code reset() override;
+    virtual error_code touchBitSetLevel(bool & sendRecvBit,
+                                        Level afterLevel) override;
+    virtual error_code writeByteSetLevel(uint_least8_t sendByte,
+                                         Level afterLevel) override;
+    virtual error_code readByteSetLevel(uint_least8_t & recvByte,
+                                        Level afterLevel) override;
+    virtual error_code writeBlock(const uint_least8_t * sendBuf,
+                                  size_t sendLen) override;
+    virtual error_code readBlock(uint_least8_t * recvBuf,
+                                 size_t recvLen) override;
+    virtual error_code setSpeed(Speed newSpeed) override;
+    virtual error_code setLevel(Level newLevel) override;
+    virtual error_code triplet(TripletData & data) override;
+
+  private:
+    DS9481P_300 * parent;
+
+    template <typename Func> error_code selectAndExecute(Func operation);
+  };
+
+  class I2CMasterImpl : public I2CMasterDecorator {
+  public:
+    explicit I2CMasterImpl(DS9481P_300 & parent) noexcept
+        : I2CMasterDecorator(parent.ds9400), parent(&parent) {}
+
+    virtual error_code start(uint_least8_t address) override;
+    virtual error_code stop() override;
+    virtual error_code writeByte(uint_least8_t data) override;
+    virtual error_code writeBlock(const uint_least8_t * data,
+                                  size_t dataLen) override;
+    virtual error_code writePacket(uint_least8_t address,
+                                   const uint_least8_t * data, size_t dataLen,
+                                   bool sendStop) override;
+    virtual error_code readByte(AckStatus status,
+                                uint_least8_t & data) override;
+    virtual error_code readBlock(AckStatus status, uint_least8_t * data,
+                                 size_t dataLen) override;
+    virtual error_code readPacket(uint_least8_t address, uint_least8_t * data,
+                                  size_t dataLen, bool sendStop) override;
+
+  private:
+    DS9481P_300 * parent;
+
+    template <typename Func> error_code selectAndExecute(Func operation);
+  };
+
+  enum class Bus { None, OneWire, I2C };
+
+  Bus currentBus;
+  OneWireLinkLayerMaster linkLayerMaster;
+  OneWireMasterImpl oneWireMaster_;
+  dotnet::Uart serial;
+  DS9400 ds9400;
+  I2CMasterImpl i2cMaster_;
+
+  error_code selectBus(Bus newBus);
+  error_code selectBus(Bus newBus, const std::string & portName);
+};
+
+inline error_code make_error_code(DS9481P_300::ErrorValue e) {
+  return error_code(e, DS9481P_300::errorCategory());
+}
+
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/dotnet/DelegateWrapper.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,118 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#pragma once
+
+#include <msclr/marshal_cppstd.h>
+#include <vcclr.h>
+
+namespace MaximInterface {
+namespace detail {
+
+template <typename DelegateT> class DelegateWrapperBase {
+public:
+  using Delegate = DelegateT;
+
+protected:
+  DelegateWrapperBase(Delegate ^ target) : target_(target) {}
+  ~DelegateWrapperBase() = default;
+
+public:
+  Delegate ^ target() const { return static_cast<Delegate ^>(target_); }
+  void setTarget(Delegate ^ target) { target_ = target; }
+  void swap(DelegateWrapperBase & other) { target_.swap(other.target_); }
+  explicit operator bool() const { return target() != nullptr; }
+
+private:
+  gcroot<Delegate ^> target_;
+};
+
+template <typename DelegateT>
+inline void swap(DelegateWrapperBase<DelegateT> & lhs,
+                 DelegateWrapperBase<DelegateT> & rhs) {
+  lhs.swap(rhs);
+}
+
+template <typename R, typename... Args>
+class DelegateWrapperImpl
+    : public DelegateWrapperBase<System::Func<Args..., R> > {
+protected:
+  DelegateWrapperImpl(Delegate ^ target) : DelegateWrapperBase(target) {}
+
+public:
+  R operator()(Args... args) { return target()(args...); }
+};
+
+template <typename... Args>
+class DelegateWrapperImpl<void, Args...>
+    : public DelegateWrapperBase<System::Action<Args...> > {
+protected:
+  DelegateWrapperImpl(Delegate ^ target) : DelegateWrapperBase(target) {}
+
+public:
+  void operator()(Args... args) const { target()(args...); }
+};
+
+} // namespace detail
+
+/// @{
+/// Functor wrapper for .NET delegates.
+template <typename> class DelegateWrapper;
+
+template <typename R, typename... Args>
+class DelegateWrapper<R(Args...)>
+    : public detail::DelegateWrapperImpl<R, Args...> {
+public:
+  DelegateWrapper(Delegate ^ target = nullptr) : DelegateWrapperImpl(target) {}
+};
+
+template <typename R, typename... Args>
+class DelegateWrapper<R __clrcall(Args...)>
+    : public detail::DelegateWrapperImpl<R, Args...> {
+public:
+  DelegateWrapper(Delegate ^ target = nullptr) : DelegateWrapperImpl(target) {}
+};
+/// @}
+
+/// Wrapper for using a .NET delegate as a MaximInterface::WriteMessage.
+class WriteMessageDelegateWrapper
+    : public DelegateWrapper<void(System::String ^)> {
+public:
+  WriteMessageDelegateWrapper(Delegate ^ target = nullptr)
+      : DelegateWrapper(target) {}
+
+  void operator()(const std::string & arg) const {
+    target()(msclr::interop::marshal_as<System::String ^>(arg));
+  }
+};
+
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/dotnet/MoveOnly.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,51 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_MoveOnly
+#define MaximInterface_MoveOnly
+
+namespace MaximInterface {
+
+class MoveOnly {
+protected:
+  MoveOnly() = default;
+  ~MoveOnly() = default;
+
+  MoveOnly(const MoveOnly &) = delete;
+  MoveOnly(MoveOnly &&) = default;
+  const MoveOnly & operator=(const MoveOnly &) = delete;
+  MoveOnly & operator=(MoveOnly &&) = default;
+};
+
+} // namespace MaximInterface
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/dotnet/OneWireLinkLayerMaster.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,337 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <stdexcept>
+#include <msclr/auto_gcroot.h>
+#include <msclr/marshal_cppstd.h>
+#include <MaximInterface/Utilities/Error.hpp>
+#include "ChangeSizeType.hpp"
+#include "OneWireLinkLayerMaster.hpp"
+
+using DalSemi::OneWire::Adapter::AdapterException;
+using System::IntPtr;
+using System::Runtime::InteropServices::Marshal;
+using System::String;
+using msclr::interop::marshal_as;
+using std::string;
+
+namespace MaximInterface {
+
+struct OneWireLinkLayerMaster::Data {
+  msclr::auto_gcroot<DalSemi::OneWire::Adapter::PortAdapter ^> adapter;
+  bool connected = false;
+};
+
+OneWireLinkLayerMaster::OneWireLinkLayerMaster(const string & adapterName)
+    : data(std::make_unique<Data>()) {
+  try {
+    data->adapter = DalSemi::OneWire::AccessProvider::GetAdapter(
+        marshal_as<String ^>(adapterName));
+  } catch (AdapterException ^ e) {
+    throw std::invalid_argument(marshal_as<string>(e->Message));
+  }
+}
+
+OneWireLinkLayerMaster::~OneWireLinkLayerMaster() = default;
+
+OneWireLinkLayerMaster::OneWireLinkLayerMaster(
+    OneWireLinkLayerMaster && rhs) noexcept = default;
+
+OneWireLinkLayerMaster & OneWireLinkLayerMaster::
+operator=(OneWireLinkLayerMaster && rhs) noexcept = default;
+
+error_code OneWireLinkLayerMaster::connect(const string & portName) {
+  if (connected()) {
+    return make_error_code(AlreadyConnectedError);
+  }
+
+  error_code result;
+  try {
+    auto adapterResult =
+        data->adapter->OpenPort(marshal_as<String ^>(portName));
+    if (adapterResult) {
+      adapterResult = data->adapter->BeginExclusive(true);
+      if (adapterResult) {
+        data->connected = true;
+      } else {
+        data->adapter->FreePort();
+        result = make_error_code(OpenPortError);
+      }
+    } else {
+      result = make_error_code(OpenPortError);
+    }
+  } catch (AdapterException ^) {
+    result = make_error_code(CommunicationError);
+  }
+  return result;
+}
+
+void OneWireLinkLayerMaster::disconnect() {
+  data->adapter->EndExclusive();
+  data->adapter->FreePort();
+  data->connected = false;
+}
+
+bool OneWireLinkLayerMaster::connected() const { return data->connected; }
+
+string OneWireLinkLayerMaster::adapterName() const {
+  return marshal_as<string>(data->adapter->AdapterName);
+}
+
+string OneWireLinkLayerMaster::portName() const {
+  return connected() ? marshal_as<string>(data->adapter->PortName) : "";
+}
+
+error_code OneWireLinkLayerMaster::reset() {
+  using DalSemi::OneWire::Adapter::OWResetResult;
+
+  error_code result;
+  try {
+    switch (data->adapter->Reset()) {
+    case OWResetResult::RESET_SHORT:
+      result = make_error_code(ShortDetectedError);
+      break;
+
+    case OWResetResult::RESET_NOPRESENCE:
+      result = make_error_code(NoSlaveError);
+      break;
+    }
+  } catch (AdapterException ^) {
+    result = make_error_code(CommunicationError);
+  }
+  return result;
+}
+
+error_code OneWireLinkLayerMaster::touchBitSetLevel(bool & sendRecvBit,
+                                                    Level afterLevel) {
+  error_code result;
+  try {
+    switch (afterLevel) {
+    case StrongLevel: {
+      auto adapterResult = data->adapter->StartPowerDelivery(
+          DalSemi::OneWire::Adapter::OWPowerStart::CONDITION_AFTER_BIT);
+      if (!adapterResult) {
+        result = make_error_code(PowerDeliveryError);
+      }
+    } break;
+
+    case NormalLevel:
+      break;
+
+    default:
+      result = make_error_code(InvalidLevelError);
+      break;
+    }
+    if (!result) {
+      if (sendRecvBit) {
+        sendRecvBit = data->adapter->GetBit();
+      } else {
+        data->adapter->PutBit(0);
+      }
+    }
+  } catch (AdapterException ^) {
+    result = make_error_code(CommunicationError);
+  }
+  return result;
+}
+
+error_code OneWireLinkLayerMaster::writeByteSetLevel(uint_least8_t sendByte,
+                                                     Level afterLevel) {
+  error_code result;
+  try {
+    switch (afterLevel) {
+    case StrongLevel: {
+      auto adapterResult = data->adapter->StartPowerDelivery(
+          DalSemi::OneWire::Adapter::OWPowerStart::CONDITION_AFTER_BYTE);
+      if (!adapterResult) {
+        result = make_error_code(PowerDeliveryError);
+      }
+    } break;
+
+    case NormalLevel:
+      break;
+
+    default:
+      result = make_error_code(InvalidLevelError);
+      break;
+    }
+    if (!result) {
+      data->adapter->PutByte(sendByte);
+    }
+  } catch (AdapterException ^) {
+    result = make_error_code(CommunicationError);
+  }
+  return result;
+}
+
+error_code OneWireLinkLayerMaster::readByteSetLevel(uint_least8_t & recvByte,
+                                                    Level afterLevel) {
+  error_code result;
+  try {
+    switch (afterLevel) {
+    case StrongLevel: {
+      auto adapterResult = data->adapter->StartPowerDelivery(
+          DalSemi::OneWire::Adapter::OWPowerStart::CONDITION_AFTER_BYTE);
+      if (!adapterResult) {
+        result = make_error_code(PowerDeliveryError);
+      }
+    } break;
+
+    case NormalLevel:
+      break;
+
+    default:
+      result = make_error_code(InvalidLevelError);
+      break;
+    }
+    if (!result) {
+      recvByte = data->adapter->GetByte();
+    }
+  } catch (AdapterException ^) {
+    result = make_error_code(CommunicationError);
+  }
+  return result;
+}
+
+error_code OneWireLinkLayerMaster::writeBlock(const uint_least8_t * sendBuf,
+                                              size_t sendLen) {
+  error_code result;
+  try {
+    changeSizeType<int>(
+        [this](const uint_least8_t * data, int dataSize) {
+          auto dataManaged = gcnew array<uint_least8_t>(dataSize);
+          Marshal::Copy(static_cast<IntPtr>(const_cast<uint_least8_t *>(data)),
+                        dataManaged, 0, dataSize);
+          this->data->adapter->DataBlock(dataManaged, 0, dataSize);
+        },
+        sendBuf, sendLen);
+  } catch (AdapterException ^) {
+    result = make_error_code(CommunicationError);
+  }
+  return result;
+}
+
+error_code OneWireLinkLayerMaster::readBlock(uint_least8_t * recvBuf,
+                                             size_t recvLen) {
+  error_code result;
+  try {
+    changeSizeType<int>(
+        [this](uint_least8_t * data, int dataSize) {
+          auto dataManaged = gcnew array<uint_least8_t>(dataSize);
+          this->data->adapter->GetBlock(dataManaged, dataSize);
+          Marshal::Copy(dataManaged, 0, static_cast<IntPtr>(data), dataSize);
+        },
+        recvBuf, recvLen);
+  } catch (AdapterException ^) {
+    result = make_error_code(CommunicationError);
+  }
+  return result;
+}
+
+error_code OneWireLinkLayerMaster::setSpeed(Speed newSpeed) {
+  using DalSemi::OneWire::Adapter::OWSpeed;
+
+  error_code result;
+  try {
+    switch (newSpeed) {
+    case OverdriveSpeed:
+      data->adapter->Speed = OWSpeed::SPEED_OVERDRIVE;
+      break;
+
+    case StandardSpeed:
+      data->adapter->Speed = OWSpeed::SPEED_REGULAR;
+      break;
+
+    default:
+      result = make_error_code(InvalidSpeedError);
+      break;
+    }
+  } catch (AdapterException ^) {
+    result = make_error_code(CommunicationError);
+  }
+  return result;
+}
+
+error_code OneWireLinkLayerMaster::setLevel(Level newLevel) {
+  error_code result;
+  try {
+    switch (newLevel) {
+    case StrongLevel: {
+      auto setResult = data->adapter->StartPowerDelivery(
+          DalSemi::OneWire::Adapter::OWPowerStart::CONDITION_NOW);
+      if (!setResult) {
+        result = make_error_code(PowerDeliveryError);
+      }
+    } break;
+
+    case NormalLevel:
+      data->adapter->SetPowerNormal();
+      break;
+
+    default:
+      result = make_error_code(InvalidLevelError);
+      break;
+    }
+  } catch (AdapterException ^) {
+    result = make_error_code(CommunicationError);
+  }
+  return result;
+}
+
+const error_category & OneWireLinkLayerMaster::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "OneWireLinkLayerMaster"; }
+
+    virtual string message(int condition) const {
+      switch (condition) {
+      case CommunicationError:
+        return "Communication Error";
+
+      case OpenPortError:
+        return "Open Port Error";
+
+      case PowerDeliveryError:
+        return "Power Delivery Error";
+
+      case AlreadyConnectedError:
+        return "Already Connected Error";
+
+      default:
+        return defaultErrorMessage(condition);
+      }
+    }
+  } instance;
+  return instance;
+}
+
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/dotnet/OneWireLinkLayerMaster.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,103 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <MaximInterface/Links/OneWireMaster.hpp>
+#include <MaximInterface/Utilities/Export.h>
+#include "MoveOnly.hpp"
+
+namespace MaximInterface {
+
+/// 1-Wire interface using the OneWireLinkLayer DLL from the Compact.NET API.
+class OneWireLinkLayerMaster : public OneWireMaster, private MoveOnly {
+public:
+  enum ErrorValue {
+    CommunicationError = 1,
+    OpenPortError,
+    PowerDeliveryError,
+    AlreadyConnectedError
+  };
+
+  /// @param adapterName Adapter type name recogized by OneWireLinkLayer.
+  MaximInterface_EXPORT OneWireLinkLayerMaster(const std::string & adapterName);
+  MaximInterface_EXPORT ~OneWireLinkLayerMaster();
+
+  MaximInterface_EXPORT
+  OneWireLinkLayerMaster(OneWireLinkLayerMaster &&) noexcept;
+  MaximInterface_EXPORT OneWireLinkLayerMaster &
+  operator=(OneWireLinkLayerMaster &&) noexcept;
+
+  /// Connect to an adapter on the specified COM port.
+  MaximInterface_EXPORT error_code connect(const std::string & portName);
+  
+  /// Disconnect from the adapter on the current COM port.
+  MaximInterface_EXPORT void disconnect();
+
+  /// Check if currently connected to an adapter.
+  /// @returns True if connected.
+  MaximInterface_EXPORT bool connected() const;
+  
+  /// Get the adapter type name.
+  MaximInterface_EXPORT std::string adapterName() const;
+  
+  /// Get the currently connected COM port name.
+  MaximInterface_EXPORT std::string portName() const;
+
+  MaximInterface_EXPORT virtual error_code reset() override;
+  MaximInterface_EXPORT virtual error_code
+  touchBitSetLevel(bool & sendRecvBit, Level afterLevel) override;
+  MaximInterface_EXPORT virtual error_code
+  writeByteSetLevel(uint_least8_t sendByte, Level afterLevel) override;
+  MaximInterface_EXPORT virtual error_code
+  readByteSetLevel(uint_least8_t & recvByte, Level afterLevel) override;
+  MaximInterface_EXPORT virtual error_code
+  writeBlock(const uint_least8_t * sendBuf, size_t sendLen) override;
+  MaximInterface_EXPORT virtual error_code readBlock(uint_least8_t * recvBuf,
+                                                     size_t recvLen) override;
+  MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed) override;
+  MaximInterface_EXPORT virtual error_code setLevel(Level newLevel) override;
+
+  MaximInterface_EXPORT static const error_category & errorCategory();
+
+private:
+  struct Data;
+  std::unique_ptr<Data> data;
+};
+
+inline error_code make_error_code(OneWireLinkLayerMaster::ErrorValue e) {
+  return error_code(e, OneWireLinkLayerMaster::errorCategory());
+}
+
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/dotnet/Sleep.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,57 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include "Sleep.hpp"
+
+namespace MaximInterface {
+namespace dotnet {
+
+void sleep(const int ms) {
+  constexpr int timeSlice_ms = 20;
+  if (ms > timeSlice_ms / 2) {
+    System::Threading::Thread::Sleep(ms);
+  } else {
+    auto watch = System::Diagnostics::Stopwatch::StartNew();
+    while (watch->ElapsedMilliseconds < ms);
+    watch->Stop();
+  }
+}
+
+Sleep & Sleep::instance() {
+  static Sleep instance;
+  return instance;
+}
+
+void Sleep::operator()(int ms) const { sleep(ms); }
+
+} // namespace dotnet
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/dotnet/Sleep.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,55 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#pragma once
+
+#include <MaximInterface/Links/Sleep.hpp>
+#include <MaximInterface/Utilities/Export.h>
+#include <MaximInterface/Utilities/Uncopyable.hpp>
+
+namespace MaximInterface {
+namespace dotnet {
+
+MaximInterface_EXPORT void sleep(int ms);
+
+class Sleep : public MaximInterface::Sleep, private Uncopyable {
+public:
+  MaximInterface_EXPORT static Sleep & instance();
+
+  MaximInterface_EXPORT virtual void operator()(int ms) const override;
+
+private:
+  Sleep() = default;
+};
+
+} // namespace dotnet
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/dotnet/Uart.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,218 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <msclr/auto_gcroot.h>
+#include <msclr/marshal_cppstd.h>
+#include <MaximInterface/Utilities/Error.hpp>
+#include "ChangeSizeType.hpp"
+#include "Sleep.hpp"
+#include "Uart.hpp"
+
+using msclr::interop::marshal_as;
+using std::string;
+using namespace System;
+using System::IO::Ports::SerialPort;
+using System::Runtime::InteropServices::Marshal;
+
+namespace MaximInterface {
+namespace dotnet {
+
+template <typename Type, typename Input> static bool isType(Input in) {
+  return dynamic_cast<Type>(in) != nullptr;
+}
+
+template <typename Func>
+static error_code executeTryCatchOperation(Func tryOperation) {
+  return executeTryCatchOperation(tryOperation, [] {});
+}
+
+template <typename TryFunc, typename CatchFunc>
+static error_code executeTryCatchOperation(TryFunc tryOperation,
+                                           CatchFunc catchOperation) {
+  error_code result;
+  try {
+    tryOperation();
+  } catch (Exception ^ e) {
+    catchOperation();
+    if (isType<ArgumentException ^>(e)) {
+      result = make_error_code(Uart::ArgumentError);
+    } else if (isType<InvalidOperationException ^>(e)) {
+      result = make_error_code(Uart::InvalidOperationError);
+    } else if (isType<System::IO::IOException ^>(e)) {
+      result = make_error_code(Uart::IOError);
+    } else if (isType<UnauthorizedAccessException ^>(e)) {
+      result = make_error_code(Uart::UnauthorizedAccessError);
+    } else if (isType<TimeoutException ^>(e)) {
+      result = make_error_code(Uart::TimeoutError);
+    } else {
+      throw;
+    }
+  }
+  return result;
+}
+
+template <typename Func>
+static error_code executeIfConnected(const Uart & serial, Func operation) {
+  return serial.connected() ? operation()
+                            : make_error_code(Uart::NotConnectedError);
+}
+
+struct Uart::Data {
+  msclr::auto_gcroot<SerialPort ^> port;
+};
+
+Uart::Uart() : data(std::make_unique<Data>()) {}
+
+Uart::~Uart() = default;
+
+Uart::Uart(Uart &&) noexcept = default;
+
+Uart & Uart::operator=(Uart &&) noexcept = default;
+
+error_code Uart::connect(const string & portName) {
+  data->port = gcnew SerialPort;
+  return executeTryCatchOperation(
+      [this, &portName] {
+        data->port->PortName = marshal_as<String ^>(portName);
+        data->port->DtrEnable = true;
+        data->port->Open();
+      },
+      [this] { data->port.reset(); });
+}
+
+void Uart::disconnect() { data->port.reset(); }
+
+bool Uart::connected() const { return data->port.get() != nullptr; }
+
+string Uart::portName() const {
+  return connected() ? marshal_as<string>(data->port->PortName) : "";
+}
+
+error_code Uart::setBaud(int_least32_t baud) {
+  return executeIfConnected(*this, [this, baud] {
+    return executeTryCatchOperation(
+        [this, baud] { data->port->BaudRate = baud; });
+  });
+}
+
+error_code Uart::sendBreak() {
+  return executeIfConnected(*this, [this] {
+    return executeTryCatchOperation([this] {
+      data->port->BreakState = true;
+      sleep(1);
+      data->port->BreakState = false;
+    });
+  });
+}
+
+error_code Uart::clearReadBuffer() {
+  return executeIfConnected(*this, [this] {
+    return executeTryCatchOperation([this] { data->port->ReadExisting(); });
+  });
+}
+
+error_code Uart::writeByte(uint_least8_t data) { return writeBlock(&data, 1); }
+
+error_code Uart::writeBlock(const uint_least8_t * data, size_t dataLen) {
+  return executeIfConnected(*this, [this, data, dataLen] {
+    return executeTryCatchOperation([this, data, dataLen] {
+      changeSizeType<int>(
+          [this](const uint_least8_t * dataChunk, int dataChunkSize) {
+            auto dataManaged = gcnew array<uint_least8_t>(dataChunkSize);
+            Marshal::Copy(
+                static_cast<IntPtr>(const_cast<uint_least8_t *>(dataChunk)),
+                dataManaged, 0, dataChunkSize);
+            this->data->port->Write(dataManaged, 0, dataChunkSize);
+          },
+          data, dataLen);
+    });
+  });
+}
+
+error_code Uart::readByte(uint_least8_t & data) {
+  return executeIfConnected(*this, [this, &data] {
+    return executeTryCatchOperation(
+        [this, &data] { data = this->data->port->ReadByte(); });
+  });
+}
+
+error_code Uart::readBlock(uint_least8_t * data, size_t dataLen) {
+  return executeIfConnected(*this, [this, data, dataLen] {
+    return executeTryCatchOperation([this, data, dataLen] {
+      changeSizeType<int>(
+          [this](uint_least8_t * dataChunk, int dataChunkSize) {
+            auto dataManaged = gcnew array<uint_least8_t>(dataChunkSize);
+            int bytesRead = 0;
+            do {
+              bytesRead += this->data->port->Read(dataManaged, bytesRead,
+                                                  dataChunkSize - bytesRead);
+            } while (bytesRead < dataChunkSize);
+            Marshal::Copy(dataManaged, 0, static_cast<IntPtr>(dataChunk),
+                          dataChunkSize);
+          },
+          data, dataLen);
+    });
+  });
+}
+
+const error_category & Uart::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "dotnet UART"; }
+
+    virtual string message(int condition) const {
+      switch (condition) {
+      case NotConnectedError:
+        return "Not Connected Error";
+
+      case ArgumentError:
+        return "Argument Error";
+
+      case InvalidOperationError:
+        return "Invalid Operation Error";
+
+      case IOError:
+        return "IO Error";
+
+      case UnauthorizedAccessError:
+        return "Unauthorized Access Error";
+
+      default:
+        return defaultErrorMessage(condition);
+      }
+    }
+  } instance;
+  return instance;
+}
+
+} // namespace dotnet
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/dotnet/Uart.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,98 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <MaximInterface/Links/Uart.hpp>
+#include <MaximInterface/Utilities/Export.h>
+#include "MoveOnly.hpp"
+
+namespace MaximInterface {
+namespace dotnet {
+
+/// UART interface using .NET type System::IO::Ports::SerialPort.
+class Uart : public MaximInterface::Uart, private MoveOnly {
+public:
+  enum ErrorValue {
+    NotConnectedError = 1,
+    ArgumentError,
+    InvalidOperationError,
+    IOError,
+    UnauthorizedAccessError
+  };
+
+  MaximInterface_EXPORT Uart();
+  MaximInterface_EXPORT ~Uart();
+
+  MaximInterface_EXPORT Uart(Uart &&) noexcept;
+  MaximInterface_EXPORT Uart & operator=(Uart &&) noexcept;
+
+  /// Connect a specified COM port.
+  MaximInterface_EXPORT error_code connect(const std::string & portName);
+  
+  /// Disconnect from the current COM port.
+  MaximInterface_EXPORT void disconnect();
+
+  /// Check if currently connected to a COM port.
+  /// @returns True if connected.
+  MaximInterface_EXPORT bool connected() const;
+  
+  /// Get the currently connected COM port name.
+  MaximInterface_EXPORT std::string portName() const;
+
+  MaximInterface_EXPORT virtual error_code setBaud(int_least32_t baud) override;
+  MaximInterface_EXPORT virtual error_code sendBreak() override;
+  MaximInterface_EXPORT virtual error_code clearReadBuffer() override;
+  MaximInterface_EXPORT virtual error_code
+  writeByte(uint_least8_t data) override;
+  MaximInterface_EXPORT virtual error_code
+  writeBlock(const uint_least8_t * data, size_t dataLen) override;
+  MaximInterface_EXPORT virtual error_code
+  readByte(uint_least8_t & data) override;
+  MaximInterface_EXPORT virtual error_code readBlock(uint_least8_t * data,
+                                                     size_t dataLen) override;
+
+  MaximInterface_EXPORT static const error_category & errorCategory();
+
+private:
+  struct Data;
+  std::unique_ptr<Data> data;
+};
+
+inline error_code make_error_code(Uart::ErrorValue e) {
+  return error_code(e, Uart::errorCategory());
+}
+
+} // namespace dotnet
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mbed/I2CMaster.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,75 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include "I2CMaster.hpp"
+
+namespace MaximInterface {
+namespace mbed {
+
+error_code I2CMaster::start(uint_least8_t address) {
+  i2c->start();
+  return writeByte(address);
+}
+
+error_code I2CMaster::stop() {
+  i2c->stop();
+  return error_code();
+}
+
+error_code I2CMaster::writeByte(uint_least8_t data) {
+  return (i2c->write(data) == 1) ? error_code() : make_error_code(NackError);
+}
+
+error_code I2CMaster::writePacket(uint_least8_t address,
+                                  const uint_least8_t * data, size_t dataLen,
+                                  bool sendStop) {
+  return (i2c->write(address, reinterpret_cast<const char *>(data), dataLen,
+                     !sendStop) == 0)
+             ? error_code()
+             : make_error_code(NackError);
+}
+
+error_code I2CMaster::readByte(AckStatus status, uint_least8_t & data) {
+  data = i2c->read(status == Ack);
+  return error_code();
+}
+
+error_code I2CMaster::readPacket(uint_least8_t address, uint_least8_t * data,
+                                 size_t dataLen, bool sendStop) {
+  return (i2c->read(address, reinterpret_cast<char *>(data), dataLen,
+                    !sendStop) == 0)
+             ? error_code()
+             : make_error_code(NackError);
+}
+
+} // namespace mbed
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mbed/I2CMaster.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,66 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_mbed_I2CMaster
+#define MaximInterface_mbed_I2CMaster
+
+#include <drivers/I2C.h>
+#include <MaximInterface/Links/I2CMaster.hpp>
+
+namespace MaximInterface {
+namespace mbed {
+
+/// Wrapper for mbed::I2C.
+class I2CMaster : public MaximInterface::I2CMaster {
+public:
+  explicit I2CMaster(::mbed::I2C & i2c) : i2c(&i2c) {}
+
+  void setI2C(::mbed::I2C & i2c) { this->i2c = &i2c; }
+
+  virtual error_code start(uint_least8_t address);
+  virtual error_code stop();
+  virtual error_code writeByte(uint_least8_t data);
+  virtual error_code writePacket(uint_least8_t address,
+                                 const uint_least8_t * data, size_t dataLen,
+                                 bool sendStop);
+  virtual error_code readByte(AckStatus status, uint_least8_t & data);
+  virtual error_code readPacket(uint_least8_t address, uint_least8_t * data,
+                                size_t dataLen, bool sendStop);
+
+private:
+  ::mbed::I2C * i2c;
+};
+
+} // namespace mbed
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mbed/Sleep.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,49 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <wait_api.h>
+#include "Sleep.hpp"
+
+namespace MaximInterface {
+namespace mbed {
+
+void sleep(int ms) { wait_ms(ms); }
+
+Sleep & Sleep::instance() {
+  static Sleep instance;
+  return instance;
+}
+
+void Sleep::operator()(int ms) const { sleep(ms); }
+
+} // namespace mbed
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mbed/Sleep.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,57 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_mbed_Sleep
+#define MaximInterface_mbed_Sleep
+
+#include <MaximInterface/Links/Sleep.hpp>
+#include <MaximInterface/Utilities/Uncopyable.hpp>
+
+namespace MaximInterface {
+namespace mbed {
+
+void sleep(int ms);
+
+class Sleep : public MaximInterface::Sleep, private Uncopyable {
+public:
+  static Sleep & instance();
+
+  virtual void operator()(int ms) const;
+
+private:
+  Sleep() {}
+};
+
+} // namespace mbed
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/GpioOneWireMaster.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,173 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifdef TARGET_MAX32600
+
+#include "GpioOneWireMaster.hpp"
+#include "owlink.h"
+#include <gpio_regs.h>
+#include <clkman_regs.h>
+
+namespace MaximInterface {
+
+static const OneWireTiming stdTiming = {
+    560, // tRSTL
+    68,  // tMSP
+    64,  // tW0L
+    8,   // tW1L
+    12,  // tMSR
+    70,  // tSLOT
+};
+
+static const OneWireTiming odTiming = {
+    56, // tRSTL
+    8,  // tMSP
+    8,  // tW0L
+    1,  // tW1L
+    1,  // tMSR
+    10, // tSLOT
+};
+
+GpioOneWireMaster::GpioOneWireMaster(PinName owGpio, PinName extSpu,
+                                     bool extSpuActiveHigh)
+    : port(PINNAME_TO_PORT(owGpio)), pin(PINNAME_TO_PIN(owGpio)),
+      speed(StandardSpeed), extSpu(extSpu), extSpuActiveHigh(extSpuActiveHigh) {
+}
+
+error_code GpioOneWireMaster::initialize() {
+  if (MXC_CLKMAN->clk_ctrl_1_gpio == MXC_E_CLKMAN_CLK_SCALE_DISABLED) {
+    MXC_CLKMAN->clk_ctrl_1_gpio = MXC_E_CLKMAN_CLK_SCALE_ENABLED;
+  }
+
+  /* Set function */
+  MXC_GPIO->func_sel[port] &= ~(0xF << (4 * pin));
+
+  /* Normal input is always enabled */
+  MXC_GPIO->in_mode[port] &= ~(0xF << (4 * pin));
+
+  writeGpioHigh();
+  setLevel(NormalLevel);
+
+  return error_code();
+}
+
+error_code GpioOneWireMaster::reset() {
+  const OneWireTiming & curTiming(speed == OverdriveSpeed ? odTiming
+                                                          : stdTiming);
+  const uint16_t tREC = curTiming.tRSTL - curTiming.tMSP; // tSLOT = 2 *tRSTL
+
+  __disable_irq(); // Enter critical section
+
+  writeGpioLow();                   // Pull low
+  ow_usdelay(curTiming.tRSTL);      // Wait specified time for reset pulse
+  writeGpioHigh();                  // Let go of pin
+  ow_usdelay(curTiming.tMSP);       // Wait specified time for master sample
+  const bool pd_pulse = readGpio(); // Get sample
+  ow_usdelay(tREC); // Wait for slot time to finish including recovery
+
+  __enable_irq(); // Exit critical section
+
+  return pd_pulse ? make_error_code(NoSlaveError) : error_code();
+}
+
+error_code GpioOneWireMaster::touchBitSetLevel(bool & sendRecvBit,
+                                               Level afterLevel) {
+  __disable_irq(); // Enter critical section
+
+  uint8_t sendRecvUint = sendRecvBit;
+  ow_bit(&sendRecvUint, &MXC_GPIO->in_val[port], &MXC_GPIO->out_val[port],
+         (1 << pin), ((speed == OverdriveSpeed) ? &odTiming : &stdTiming));
+  setLevel(afterLevel);
+  sendRecvBit = sendRecvUint;
+
+  __enable_irq(); // Exit critical section
+
+  return error_code();
+}
+
+error_code GpioOneWireMaster::setSpeed(Speed newSpeed) {
+  if (!((newSpeed == StandardSpeed) || (newSpeed == OverdriveSpeed))) {
+    return make_error_code(InvalidSpeedError);
+  }
+  speed = newSpeed;
+  return error_code();
+}
+
+error_code GpioOneWireMaster::setLevel(Level newLevel) {
+  error_code result;
+  switch (newLevel) {
+  case NormalLevel:
+    setGpioMode(MXC_V_GPIO_OUT_MODE_OPEN_DRAIN);
+    if (extSpu.is_connected()) {
+      extSpu = !extSpuActiveHigh;
+    }
+    break;
+
+  case StrongLevel:
+    if (extSpu.is_connected()) {
+      extSpu = extSpuActiveHigh;
+    } else {
+      setGpioMode(MXC_V_GPIO_OUT_MODE_NORMAL_DRIVE);
+    }
+    break;
+
+  default:
+    result = make_error_code(InvalidLevelError);
+    break;
+  }
+  return result;
+}
+
+inline void GpioOneWireMaster::writeGpioLow() {
+  MXC_GPIO->out_val[port] &= ~(1 << pin);
+}
+
+inline void GpioOneWireMaster::writeGpioHigh() {
+  MXC_GPIO->out_val[port] |= (1 << pin);
+}
+
+inline bool GpioOneWireMaster::readGpio() {
+  return ((MXC_GPIO->in_val[port] & (1 << pin)) >> pin);
+}
+
+inline void GpioOneWireMaster::setGpioMode(unsigned int mode) {
+  //read port out_mode
+  uint32_t ow_out_mode = MXC_GPIO->out_mode[port];
+  //clear the mode for ow_pin
+  ow_out_mode &= ~(0xF << (pin * 4));
+  //write ow_pin mode and original data back
+  MXC_GPIO->out_mode[port] = (ow_out_mode | (mode << (pin * 4)));
+}
+
+} // namespace MaximInterface
+
+#endif /* TARGET_MAX32600 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/GpioOneWireMaster.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,70 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_GpioOneWireMaster
+#define MaximInterface_GpioOneWireMaster
+
+#include <MaximInterface/Links/OneWireMaster.hpp>
+#include <DigitalOut.h>
+
+namespace MaximInterface {
+
+class GpioOneWireMaster : public OneWireMaster {
+public:
+  /// @param owGpio Pin to use for 1-Wire bus
+  /// @param extSpu Pin to use for external Strong Pullup
+  explicit GpioOneWireMaster(PinName owGpio, PinName extSpu = NC,
+                             bool extSpuActiveHigh = false);
+
+  error_code initialize();
+
+  virtual error_code reset();
+  virtual error_code touchBitSetLevel(bool & sendRecvBit, Level afterLevel);
+  virtual error_code setSpeed(Speed newSpeed);
+  virtual error_code setLevel(Level newLevel);
+
+private:
+  unsigned int port;
+  unsigned int pin;
+  Speed speed;
+  mbed::DigitalOut extSpu;
+  bool extSpuActiveHigh;
+
+  inline void writeGpioLow();
+  inline void writeGpioHigh();
+  inline bool readGpio();
+  inline void setGpioMode(unsigned int mode);
+};
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_ARM_STD/owlink.s	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,199 @@
+/******************************************************************//**
+* Copyright (C) 2016 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+**********************************************************************/
+
+// ow_usdelay configuration
+#define PROC_CLOCK_MHZ (__SYSTEM_HFX / 1000000) // Processor clock in MHz
+#define OVERHEAD_TUNING 18 // Fraction where OverheadTime(us) = OVERHEAD_TUNING / PROC_CLOCK_MHZ
+// Make PROC_CLOCK_MHZ and OVERHEAD_TUNING divisible by PROC_CYCLES_PER_LOOP for best results
+
+// ow_usdelay constants
+#define PIPELINE_REFILL_PROC_CYCLES 1 // ARM specifies 1-3 cycles for pipeline refill following a branch
+#define PROC_CYCLES_PER_LOOP (2 + PIPELINE_REFILL_PROC_CYCLES)
+#define LOOPS_PER_US (PROC_CLOCK_MHZ / PROC_CYCLES_PER_LOOP) // Number of loop passes for a 1 us delay
+#define LOOPS_REMOVED_TUNING (OVERHEAD_TUNING / PROC_CYCLES_PER_LOOP)
+
+// OwTiming offsets
+#define tRSTL_OFFSET    0
+#define tMSP_OFFSET     2
+#define tW0L_OFFSET     4
+#define tW1L_OFFSET     6
+#define tMSR_OFFSET     8
+#define tSLOT_OFFSET   10
+
+// Define a code section
+  AREA owlink, CODE
+// void ow_usdelay(unsigned int time_us)
+  EXPORT ow_usdelay
+ow_usdelay
+  cmp R0, #0 // Return if time_us equals zero
+  beq ow_usdelay_return
+  mov R2, #LOOPS_PER_US
+  mul R0, R0, R2
+  sub R0, R0, #LOOPS_REMOVED_TUNING
+loop
+  subs R0, R0, #1
+  bne loop
+ow_usdelay_return
+  bx R14
+  
+// static void write_ow_gpio_low(unsigned int * portReg, unsigned int pinMask)
+  MACRO
+$label write_ow_gpio_low
+  ldr R2, [R0]
+  bic R2, R2, R1
+  str R2, [R0]
+  MEND
+  
+// static void write_ow_gpio_high(unsigned int * portReg, unsigned int pinMask)
+  MACRO
+$label write_ow_gpio_high
+  ldr R2, [R0]
+  orr R2, R2, R1
+  str R2, [R0]
+  MEND
+  
+// void ow_bit(uint8_t * sendrecvbit, volatile uint32_t * inPortReg, volatile uint32_t * outPortReg, unsigned int pinMask, const OwTiming * timing)
+  EXPORT ow_bit
+ow_bit
+  push {R4-R8, R14}
+  // Retrive extra parameters from stack
+  add R6, SP, #24 // Find beginning of stack: 6 scratch registers * 4 bytes each
+  ldr R6, [R6] // Load timing struct
+  ldrh R4, [R6, #tSLOT_OFFSET]
+  ldrh R5, [R6, #tMSR_OFFSET]
+  // R0: sendrecvbit
+  // R1: inPortReg
+  // R2: outPortReg
+  // R3: pinMask
+  // R4: tSLOT
+  // R5: tMSR
+  // R6: timing
+  // R7: Scratch
+  // R8: Scratch
+  // R14: Scratch
+  
+  // Reorganize registers for upcoming function calls
+  mov R8, R1 // inPortReg to R8
+  mov R7, R2 // outPortReg to R7
+  mov R1, R3 // pinMask to R1
+  mov R3, R0 // sendrecvbit to R3
+  // R0: Scratch
+  // R1: pinMask
+  // R2: Scratch
+  // R3: sendrecvbit
+  // R4: tSLOT
+  // R5: tMSR
+  // R6: timing
+  // R7: outPortReg
+  // R8: inPortReg
+  // R14: Scratch
+  
+  // if (*sendrecvbit & 1)
+  ldrb R14, [R3]
+  tst R14, #1
+  beq write_zero
+  ldrh R6, [R6, #tW1L_OFFSET] // tW1L
+  sub R4, R4, R5 // tREC = tSLOT - tMSR
+  sub R5, R5, R6 // delay2 = tMSR - tLW1L
+  // R0: Scratch
+  // R1: pinMask
+  // R2: Scratch
+  // R3: sendrecvbit
+  // R4: tREC
+  // R5: delay2
+  // R6: tW1L
+  // R7: outPortReg
+  // R8: inPortReg
+  // R14: Scratch
+  mov R0, R7 // outPortReg
+  write_ow_gpio_low // Pull low
+  mov R0, R6 // tLOW
+  bl ow_usdelay // Delay for tLOW
+  mov R0, R7 // outPortReg
+  write_ow_gpio_high // Release pin
+  mov R0, R5 // delay2
+  bl ow_usdelay // Delay for sample time
+  ldr R5, [R8] // Read *inPortReg
+  b recovery_delay
+  // else
+write_zero
+  ldrh R6, [R6, #tW0L_OFFSET] // tW0L
+  sub R4, R4, R6 // tREC = tSLOT - tLW0L
+  sub R6, R6, R5 // delay2 = tW0L - tMSR
+  // R0: Scratch
+  // R1: pinMask
+  // R2: Scratch
+  // R3: sendrecvbit
+  // R4: tREC
+  // R5: tMSR
+  // R6: delay2
+  // R7: outPortReg
+  // R8: inPortReg
+  // R14: Scratch
+  mov R0, R7 // outPortReg
+  write_ow_gpio_low // Pull low
+  mov R0, R5 // tMSR
+  bl ow_usdelay // Delay for tMSR
+  ldr R5, [R8] // Read *inPortReg
+  mov R0, R6 // delay2
+  bl ow_usdelay // Delay for release
+  mov R0, R7 // outPortReg
+  write_ow_gpio_high // Release pin
+  // endif (*sendrecvbit & 1)
+  // R0: Scratch
+  // R1: pinMask
+  // R2: Scratch
+  // R3: sendrecvbit
+  // R4: tREC
+  // R5: *inPortReg
+  // R6: Scratch
+  // R7: outPortReg
+  // R8: inPortReg
+  // R14: Scratch
+  
+recovery_delay
+  mov R0, R4
+  bl ow_usdelay // Delay for tREC
+  
+  // Parse received bit
+  // *sendrecvbit = ((*inPortReg & pinMask) == pinMask)
+  and R5, R5, R1
+  cmp R5, R1
+  ite eq
+  moveq R5, #1
+  movne R5, #0
+  strb R5, [R3]
+  
+  pop {R4-R8, R14}
+  bx R14
+  
+  END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_GCC_ARM/owlink.S	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,200 @@
+/******************************************************************//**
+* Copyright (C) 2016 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+**********************************************************************/
+
+// ow_usdelay configuration
+#define PROC_CLOCK_MHZ (__SYSTEM_HFX / 1000000) // Processor clock in MHz
+#define OVERHEAD_TUNING 18 // Fraction where OverheadTime(us) = OVERHEAD_TUNING / PROC_CLOCK_MHZ
+// Make PROC_CLOCK_MHZ and OVERHEAD_TUNING divisible by PROC_CYCLES_PER_LOOP for best results
+
+// ow_usdelay constants
+#define PIPELINE_REFILL_PROC_CYCLES 1 // ARM specifies 1-3 cycles for pipeline refill following a branch
+#define PROC_CYCLES_PER_LOOP (2 + PIPELINE_REFILL_PROC_CYCLES)
+#define LOOPS_PER_US (PROC_CLOCK_MHZ / PROC_CYCLES_PER_LOOP) // Number of loop passes for a 1 us delay
+#define LOOPS_REMOVED_TUNING (OVERHEAD_TUNING / PROC_CYCLES_PER_LOOP)
+
+// OwTiming offsets
+#define tRSTL_OFFSET    0
+#define tMSP_OFFSET     2
+#define tW0L_OFFSET     4
+#define tW1L_OFFSET     6
+#define tMSR_OFFSET     8
+#define tSLOT_OFFSET   10
+
+// Define a code section
+  .syntax unified
+  .section .text
+// void ow_usdelay(unsigned int time_us)
+  .thumb_func
+  .global ow_usdelay
+ow_usdelay:
+  cmp R0, #0 // Return if time_us equals zero
+  beq ow_usdelay_return
+  mov R2, #LOOPS_PER_US
+  mul R0, R0, R2
+  sub R0, R0, #LOOPS_REMOVED_TUNING
+loop:
+  subs R0, R0, #1
+  bne loop
+ow_usdelay_return:
+  bx R14
+  
+// static void write_ow_gpio_low(unsigned int * portReg, unsigned int pinMask)
+.macro write_ow_gpio_low
+  ldr R2, [R0]
+  bic R2, R2, R1
+  str R2, [R0]
+  .endm
+  
+// static void write_ow_gpio_high(unsigned int * portReg, unsigned int pinMask)
+.macro write_ow_gpio_high
+  ldr R2, [R0]
+  orr R2, R2, R1
+  str R2, [R0]
+  .endm
+  
+// void ow_bit(uint8_t * sendrecvbit, volatile uint32_t * inPortReg, volatile uint32_t * outPortReg, unsigned int pinMask, const OwTiming * timing)
+  .thumb_func
+  .global ow_bit
+ow_bit:
+  push {R4-R8, R14}
+  // Retrive extra parameters from stack
+  add R6, SP, #24 // Find beginning of stack: 6 scratch registers * 4 bytes each
+  ldr R6, [R6] // Load timing struct
+  ldrh R4, [R6, #tSLOT_OFFSET]
+  ldrh R5, [R6, #tMSR_OFFSET]
+  // R0: sendrecvbit
+  // R1: inPortReg
+  // R2: outPortReg
+  // R3: pinMask
+  // R4: tSLOT
+  // R5: tMSR
+  // R6: timing
+  // R7: Scratch
+  // R8: Scratch
+  // R14: Scratch
+  
+  // Reorganize registers for upcoming function calls
+  mov R8, R1 // inPortReg to R8
+  mov R7, R2 // outPortReg to R7
+  mov R1, R3 // pinMask to R1
+  mov R3, R0 // sendrecvbit to R3
+  // R0: Scratch
+  // R1: pinMask
+  // R2: Scratch
+  // R3: sendrecvbit
+  // R4: tSLOT
+  // R5: tMSR
+  // R6: timing
+  // R7: outPortReg
+  // R8: inPortReg
+  // R14: Scratch
+  
+  // if (*sendrecvbit & 1)
+  ldrb R14, [R3]
+  tst R14, #1
+  beq write_zero
+  ldrh R6, [R6, #tW1L_OFFSET] // tW1L
+  sub R4, R4, R5 // tREC = tSLOT - tMSR
+  sub R5, R5, R6 // delay2 = tMSR - tLW1L
+  // R0: Scratch
+  // R1: pinMask
+  // R2: Scratch
+  // R3: sendrecvbit
+  // R4: tREC
+  // R5: delay2
+  // R6: tW1L
+  // R7: outPortReg
+  // R8: inPortReg
+  // R14: Scratch
+  mov R0, R7 // outPortReg
+  write_ow_gpio_low // Pull low
+  mov R0, R6 // tLOW
+  bl ow_usdelay // Delay for tLOW
+  mov R0, R7 // outPortReg
+  write_ow_gpio_high // Release pin
+  mov R0, R5 // delay2
+  bl ow_usdelay // Delay for sample time
+  ldr R5, [R8] // Read *inPortReg
+  b recovery_delay
+  // else
+write_zero:
+  ldrh R6, [R6, #tW0L_OFFSET] // tW0L
+  sub R4, R4, R6 // tREC = tSLOT - tLW0L
+  sub R6, R6, R5 // delay2 = tW0L - tMSR
+  // R0: Scratch
+  // R1: pinMask
+  // R2: Scratch
+  // R3: sendrecvbit
+  // R4: tREC
+  // R5: tMSR
+  // R6: delay2
+  // R7: outPortReg
+  // R8: inPortReg
+  // R14: Scratch
+  mov R0, R7 // outPortReg
+  write_ow_gpio_low // Pull low
+  mov R0, R5 // tMSR
+  bl ow_usdelay // Delay for tMSR
+  ldr R5, [R8] // Read *inPortReg
+  mov R0, R6 // delay2
+  bl ow_usdelay // Delay for release
+  mov R0, R7 // outPortReg
+  write_ow_gpio_high // Release pin
+  // endif (*sendrecvbit & 1)
+  // R0: Scratch
+  // R1: pinMask
+  // R2: Scratch
+  // R3: sendrecvbit
+  // R4: tREC
+  // R5: *inPortReg
+  // R6: Scratch
+  // R7: outPortReg
+  // R8: inPortReg
+  // R14: Scratch
+  
+recovery_delay:
+  mov R0, R4
+  bl ow_usdelay // Delay for tREC
+  
+  // Parse received bit
+  // *sendrecvbit = ((*inPortReg & pinMask) == pinMask)
+  and R5, R5, R1
+  cmp R5, R1
+  ite eq
+  moveq R5, #1
+  movne R5, #0
+  strb R5, [R3]
+  
+  pop {R4-R8, R14}
+  bx R14
+  .end
+  
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_IAR/owlink.s	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,197 @@
+/******************************************************************//**
+* Copyright (C) 2016 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+**********************************************************************/
+
+// ow_usdelay configuration
+#define PROC_CLOCK_MHZ (__SYSTEM_HFX / 1000000) // Processor clock in MHz
+#define OVERHEAD_TUNING 18 // Fraction where OverheadTime(us) = OVERHEAD_TUNING / PROC_CLOCK_MHZ
+// Make PROC_CLOCK_MHZ and OVERHEAD_TUNING divisible by PROC_CYCLES_PER_LOOP for best results
+
+// ow_usdelay constants
+#define PIPELINE_REFILL_PROC_CYCLES 1 // ARM specifies 1-3 cycles for pipeline refill following a branch
+#define PROC_CYCLES_PER_LOOP (2 + PIPELINE_REFILL_PROC_CYCLES)
+#define LOOPS_PER_US (PROC_CLOCK_MHZ / PROC_CYCLES_PER_LOOP) // Number of loop passes for a 1 us delay
+#define LOOPS_REMOVED_TUNING (OVERHEAD_TUNING / PROC_CYCLES_PER_LOOP)
+
+// OwTiming offsets
+#define tRSTL_OFFSET    0
+#define tMSP_OFFSET     2
+#define tW0L_OFFSET     4
+#define tW1L_OFFSET     6
+#define tMSR_OFFSET     8
+#define tSLOT_OFFSET   10
+
+// Define a code section 
+  SECTION owlink : CODE
+
+// void ow_usdelay(unsigned int time_us)
+  EXPORT ow_usdelay
+ow_usdelay
+  cmp R0, #0 // Return if time_us equals zero
+  beq ow_usdelay_return
+  mov R2, #LOOPS_PER_US
+  mul R0, R0, R2
+  sub R0, R0, #LOOPS_REMOVED_TUNING
+loop
+  subs R0, R0, #1
+  bne loop
+ow_usdelay_return
+  bx R14
+  
+// static void write_ow_gpio_low(unsigned int * portReg, unsigned int pinMask)
+write_ow_gpio_low MACRO
+  ldr R2, [R0]
+  bic R2, R2, R1
+  str R2, [R0]
+  ENDM
+  
+// static void write_ow_gpio_high(unsigned int * portReg, unsigned int pinMask)
+write_ow_gpio_high MACRO
+  ldr R2, [R0]
+  orr R2, R2, R1
+  str R2, [R0]
+  ENDM
+  
+// void ow_bit(uint8_t * sendrecvbit, volatile uint32_t * inPortReg, volatile uint32_t * outPortReg, unsigned int pinMask, const OwTiming * timing)
+  EXPORT ow_bit
+ow_bit
+  push {R4-R8, R14}
+  // Retrive extra parameters from stack
+  add R6, SP, #24 // Find beginning of stack: 6 scratch registers * 4 bytes each
+  ldr R6, [R6] // Load timing struct
+  ldrh R4, [R6, #tSLOT_OFFSET]
+  ldrh R5, [R6, #tMSR_OFFSET]
+  // R0: sendrecvbit
+  // R1: inPortReg
+  // R2: outPortReg
+  // R3: pinMask
+  // R4: tSLOT
+  // R5: tMSR
+  // R6: timing
+  // R7: Scratch
+  // R8: Scratch
+  // R14: Scratch
+  
+  // Reorganize registers for upcoming function calls
+  mov R8, R1 // inPortReg to R8
+  mov R7, R2 // outPortReg to R7
+  mov R1, R3 // pinMask to R1
+  mov R3, R0 // sendrecvbit to R3
+  // R0: Scratch
+  // R1: pinMask
+  // R2: Scratch
+  // R3: sendrecvbit
+  // R4: tSLOT
+  // R5: tMSR
+  // R6: timing
+  // R7: outPortReg
+  // R8: inPortReg
+  // R14: Scratch
+  
+  // if (*sendrecvbit & 1)
+  ldrb R14, [R3]
+  tst R14, #1
+  beq write_zero
+  ldrh R6, [R6, #tW1L_OFFSET] // tW1L
+  sub R4, R4, R5 // tREC = tSLOT - tMSR
+  sub R5, R5, R6 // delay2 = tMSR - tLW1L
+  // R0: Scratch
+  // R1: pinMask
+  // R2: Scratch
+  // R3: sendrecvbit
+  // R4: tREC
+  // R5: delay2
+  // R6: tW1L
+  // R7: outPortReg
+  // R8: inPortReg
+  // R14: Scratch
+  mov R0, R7 // outPortReg
+  write_ow_gpio_low // Pull low
+  mov R0, R6 // tLOW
+  bl ow_usdelay // Delay for tLOW
+  mov R0, R7 // outPortReg
+  write_ow_gpio_high // Release pin
+  mov R0, R5 // delay2
+  bl ow_usdelay // Delay for sample time
+  ldr R5, [R8] // Read *inPortReg
+  b recovery_delay
+  // else
+write_zero
+  ldrh R6, [R6, #tW0L_OFFSET] // tW0L
+  sub R4, R4, R6 // tREC = tSLOT - tLW0L
+  sub R6, R6, R5 // delay2 = tW0L - tMSR
+  // R0: Scratch
+  // R1: pinMask
+  // R2: Scratch
+  // R3: sendrecvbit
+  // R4: tREC
+  // R5: tMSR
+  // R6: delay2
+  // R7: outPortReg
+  // R8: inPortReg
+  // R14: Scratch
+  mov R0, R7 // outPortReg
+  write_ow_gpio_low // Pull low
+  mov R0, R5 // tMSR
+  bl ow_usdelay // Delay for tMSR
+  ldr R5, [R8] // Read *inPortReg
+  mov R0, R6 // delay2
+  bl ow_usdelay // Delay for release
+  mov R0, R7 // outPortReg
+  write_ow_gpio_high // Release pin
+  // endif (*sendrecvbit & 1)
+  // R0: Scratch
+  // R1: pinMask
+  // R2: Scratch
+  // R3: sendrecvbit
+  // R4: tREC
+  // R5: *inPortReg
+  // R6: Scratch
+  // R7: outPortReg
+  // R8: inPortReg
+  // R14: Scratch
+  
+recovery_delay
+  mov R0, R4
+  bl ow_usdelay // Delay for tREC
+  
+  // Parse received bit
+  // *sendrecvbit = ((*inPortReg & pinMask) == pinMask)
+  and R5, R5, R1
+  cmp R5, R1
+  ite eq
+  moveq R5, #1
+  movne R5, #0
+  strb R5, [R3]
+  
+  pop {R4-R8, R14}
+  bx R14
+  END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/owlink.h	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,72 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_owlink
+#define MaximInterface_owlink
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Timing parameters for the 1-Wire bus.
+/// @note All times are in terms of microseconds.
+struct OneWireTiming {
+  uint16_t tRSTL; ///< Reset Low Time
+  uint16_t tMSP;  ///< Presence-Detect Sample Time
+  uint16_t tW0L;  ///< Write-Zero Low Time
+  uint16_t tW1L;  ///< Write-One Low Time
+  uint16_t tMSR;  ///< Read Sample Time
+  uint16_t tSLOT; ///< Time Slot Duration
+};
+
+/// Delay for the specified number of microseconds.
+void ow_usdelay(unsigned int time_us);
+
+/// Send and receive one bit of communication and set a new level on the 1-Wire bus.
+/// @note GPIO pin must be configured for open drain operation.
+/// @param[in,out] sendRecvBit Buffer containing the bit to send on 1-Wire bus in lsb.
+///                            Read data from 1-Wire bus will be returned in lsb.
+/// @param inReg Input register for GPIO pin.
+/// @param outReg Output register for GPIO pin.
+/// @param pinMask Pin mask for input and output registers.
+/// @param[in] timing 1-Wire timing parameters to use.
+void ow_bit(uint8_t * sendRecvBit, volatile uint32_t * inReg,
+            volatile uint32_t * outPortReg, unsigned int pinMask,
+            const OneWireTiming * timing);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MaximInterface_owlink */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mbed/Uart.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,106 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <MaximInterface/Utilities/Error.hpp>
+#include <Timer.h>
+#include "Uart.hpp"
+
+static const int timeout_ms = 10000;
+
+namespace MaximInterface {
+namespace mbed {
+
+error_code Uart::setBaud(int_least32_t baud) {
+  serial->baud(baud);
+  return error_code();
+}
+
+error_code Uart::sendBreak() {
+  serial->send_break();
+  return error_code();
+}
+
+error_code Uart::clearReadBuffer() {
+  while (serial->readable()) {
+    serial->getc();
+  }
+  return error_code();
+}
+
+error_code Uart::writeByte(uint_least8_t data) {
+  if (!serial->writeable()) {
+    ::mbed::Timer timer;
+    timer.start();
+    while (!serial->writeable()) {
+      if (timer.read_ms() >= timeout_ms) {
+        return make_error_code(HardwareError);
+      }
+    }
+  }
+  serial->putc(data);
+  return error_code();
+}
+
+error_code Uart::readByte(uint_least8_t & data) {
+  if (!serial->readable()) {
+    ::mbed::Timer timer;
+    timer.start();
+    while (!serial->readable()) {
+      if (timer.read_ms() >= timeout_ms) {
+        return make_error_code(TimeoutError);
+      }
+    }
+  }
+  data = serial->getc();
+  return error_code();
+}
+
+const error_category & Uart::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "mbed UART"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case HardwareError:
+        return "Hardware Error";
+
+      default:
+        return defaultErrorMessage(condition);
+      }
+    }
+  } instance;
+  return instance;
+}
+
+} // namespace mbed
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mbed/Uart.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,72 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_mbed_Uart
+#define MaximInterface_mbed_Uart
+
+#include <drivers/Serial.h>
+#include <MaximInterface/Links/Uart.hpp>
+
+namespace MaximInterface {
+namespace mbed {
+
+/// Wrapper for mbed::Serial.
+class Uart : public MaximInterface::Uart {
+public:
+  enum ErrorValue {
+    HardwareError = 1 ///< Write operation aborted due to timeout.
+  };
+
+  explicit Uart(::mbed::Serial & serial) : serial(&serial) {}
+
+  void setSerial(::mbed::Serial & serial) { this->serial = &serial; }
+
+  virtual error_code setBaud(int_least32_t baud);
+  virtual error_code sendBreak();
+  virtual error_code clearReadBuffer();
+  virtual error_code writeByte(uint_least8_t data);
+  virtual error_code readByte(uint_least8_t & data);
+
+  static const error_category & errorCategory();
+
+private:
+  ::mbed::Serial * serial;
+};
+
+inline error_code make_error_code(Uart::ErrorValue e) {
+  return error_code(e, Uart::errorCategory());
+}
+
+} // namespace mbed
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mxc/.mbedignore	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,1 @@
+*
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mxc/Error.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,61 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <MaximInterface/Links/I2CMaster.hpp>
+#include <MaximInterface/Utilities/Error.hpp>
+#include <mxc_errors.h>
+#include "Error.hpp"
+
+namespace MaximInterface {
+namespace mxc {
+
+const error_category & errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "mxc"; }
+
+    virtual std::string message(int condition) const {
+      return defaultErrorMessage(condition);
+    }
+
+    // Make E_COMM_ERR equivalent to I2CMaster::NackError.
+    virtual bool equivalent(int code, const error_condition & condition) const {
+      return (code == E_COMM_ERR)
+                 ? (condition == make_error_condition(I2CMaster::NackError))
+                 : error_category::equivalent(code, condition);
+    }
+  } instance;
+  return instance;
+}
+
+} // namespace mxc
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mxc/Error.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,53 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+/// @file Common functionality for mapping mxc return codes to
+/// MaximInterface::error_code.
+
+#ifndef MaximInterface_mxc_Error
+#define MaximInterface_mxc_Error
+
+#include <MaximInterface/Utilities/system_error.hpp>
+
+namespace MaximInterface {
+namespace mxc {
+
+const error_category & errorCategory();
+
+inline error_code makeErrorCode(int mxcResult) {
+  return error_code(mxcResult, errorCategory());
+}
+
+} // namespace mxc
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mxc/I2CMaster.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,116 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <mxc_device.h>
+#include "Error.hpp"
+#include "I2CMaster.hpp"
+
+namespace MaximInterface {
+namespace mxc {
+
+static void verifyTransactionStarted(mxc_i2cm_regs_t & i2cm) {
+  if (!(i2cm.trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS)) {
+    i2cm.trans |= MXC_F_I2CM_TRANS_TX_START;
+  }
+}
+
+error_code I2CMaster::initialize(const sys_cfg_i2cm_t & sysCfg,
+                                 i2cm_speed_t speed) {
+  return makeErrorCode(I2CM_Init(i2cm, &sysCfg, speed));
+}
+
+error_code I2CMaster::shutdown() { return makeErrorCode(I2CM_Shutdown(i2cm)); }
+
+error_code I2CMaster::writeByte(uint_least8_t data, bool start) {
+  const uint16_t fifoData =
+      static_cast<uint16_t>(data & 0xFF) |
+      (start ? MXC_S_I2CM_TRANS_TAG_START : MXC_S_I2CM_TRANS_TAG_TXDATA_ACK);
+  const error_code result =
+      makeErrorCode(I2CM_WriteTxFifo(i2cm, i2cmFifo, fifoData));
+  if (result) {
+    I2CM_Recover(i2cm);
+  } else {
+    verifyTransactionStarted(*i2cm);
+  }
+  return result;
+}
+
+error_code I2CMaster::start(uint_least8_t address) {
+  return writeByte(address, true);
+}
+
+error_code I2CMaster::stop() {
+  error_code result = makeErrorCode(
+      I2CM_WriteTxFifo(i2cm, i2cmFifo, MXC_S_I2CM_TRANS_TAG_STOP));
+  if (!result) {
+    result = makeErrorCode(I2CM_TxInProgress(i2cm));
+  }
+  return result;
+}
+
+error_code I2CMaster::writeByte(uint_least8_t data) {
+  return writeByte(data, false);
+}
+
+error_code I2CMaster::readByte(AckStatus status, uint_least8_t & data) {
+  uint16_t fifoData = (status == Nack) ? MXC_S_I2CM_TRANS_TAG_RXDATA_NACK
+                                       : MXC_S_I2CM_TRANS_TAG_RXDATA_COUNT;
+  error_code result = makeErrorCode(I2CM_WriteTxFifo(i2cm, i2cmFifo, fifoData));
+  if (!result) {
+    verifyTransactionStarted(*i2cm);
+    do {
+      int timeout = 0x5000;
+      while ((i2cm->bb & MXC_F_I2CM_BB_RX_FIFO_CNT) == 0) {
+        if ((--timeout <= 0) || (i2cm->trans & MXC_F_I2CM_TRANS_TX_TIMEOUT)) {
+          result = makeErrorCode(E_TIME_OUT);
+          goto exit;
+        }
+        if (i2cm->trans &
+            (MXC_F_I2CM_TRANS_TX_LOST_ARBITR | MXC_F_I2CM_TRANS_TX_NACKED)) {
+          result = make_error_code(NackError);
+          goto exit;
+        }
+      }
+      fifoData = i2cmFifo->rx;
+    } while (fifoData & MXC_S_I2CM_RSTLS_TAG_EMPTY);
+    data = fifoData & 0xFF;
+  }
+
+exit:
+  if (result) {
+    I2CM_Recover(i2cm);
+  }
+  return result;
+}
+
+} // namespace mxc
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mxc/I2CMaster.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,73 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_mxc_I2CMaster
+#define MaximInterface_mxc_I2CMaster
+
+#include <MaximInterface/Links/I2CMaster.hpp>
+#include <i2cm.h>
+
+namespace MaximInterface {
+namespace mxc {
+
+class I2CMaster : public MaximInterface::I2CMaster {
+public:
+  I2CMaster(mxc_i2cm_regs_t & i2cm, mxc_i2cm_fifo_regs_t & i2cmFifo)
+      : i2cm(&i2cm), i2cmFifo(&i2cmFifo) {}
+
+  void set_mxc_i2cm(mxc_i2cm_regs_t & i2cm, mxc_i2cm_fifo_regs_t & i2cmFifo) {
+    this->i2cm = &i2cm;
+    this->i2cmFifo = &i2cmFifo;
+  }
+
+  /// Initialize the hardware interface for use.
+  error_code initialize(const sys_cfg_i2cm_t & sysCfg, i2cm_speed_t speed);
+  
+  /// Shutdown the hardware interface after use.
+  error_code shutdown();
+
+  virtual error_code start(uint_least8_t address);
+  virtual error_code stop();
+  virtual error_code writeByte(uint_least8_t data);
+  virtual error_code readByte(AckStatus status, uint_least8_t & data);
+
+private:
+  error_code writeByte(uint_least8_t data, bool start);
+
+  mxc_i2cm_regs_t * i2cm;
+  mxc_i2cm_fifo_regs_t * i2cmFifo;
+};
+
+} // namespace mxc
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mxc/OneWireMaster.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,103 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include "Error.hpp"
+#include "OneWireMaster.hpp"
+
+namespace MaximInterface {
+namespace mxc {
+
+error_code OneWireMaster::initialize(const owm_cfg_t & owmCfg,
+                                     const sys_cfg_owm_t & sysCfgOwm) {
+  extStrongPup = (owmCfg.ext_pu_mode != OWM_EXT_PU_UNUSED);
+  return makeErrorCode(OWM_Init(owm, &owmCfg, &sysCfgOwm));
+}
+
+error_code OneWireMaster::shutdown() {
+  return makeErrorCode(OWM_Shutdown(owm));
+}
+
+error_code OneWireMaster::reset() {
+  return OWM_Reset(owm) ? error_code() : make_error_code(NoSlaveError);
+}
+
+error_code OneWireMaster::touchBitSetLevel(bool & sendRecvBit,
+                                           Level afterLevel) {
+  sendRecvBit = OWM_TouchBit(owm, sendRecvBit);
+  return setLevel(afterLevel);
+}
+
+error_code OneWireMaster::writeByteSetLevel(uint_least8_t sendByte,
+                                            Level afterLevel) {
+  error_code result = makeErrorCode(OWM_WriteByte(owm, sendByte));
+  if (!result) {
+    result = setLevel(afterLevel);
+  }
+  return result;
+}
+
+error_code OneWireMaster::readByteSetLevel(uint_least8_t & recvByte,
+                                           Level afterLevel) {
+  recvByte = OWM_ReadByte(owm);
+  return setLevel(afterLevel);
+}
+
+error_code OneWireMaster::setSpeed(Speed newSpeed) {
+  error_code result;
+  if (newSpeed == OverdriveSpeed) {
+    OWM_SetOverdrive(owm, 1);
+  } else if (newSpeed == StandardSpeed) {
+    OWM_SetOverdrive(owm, 0);
+  } else {
+    result = make_error_code(InvalidSpeedError);
+  }
+  return result;
+}
+
+error_code OneWireMaster::setLevel(Level newLevel) {
+  error_code result;
+  if (extStrongPup) {
+    if (newLevel == StrongLevel) {
+      OWM_SetExtPullup(owm, 1);
+    } else if (newLevel == NormalLevel) {
+      OWM_SetExtPullup(owm, 0);
+    } else {
+      result = make_error_code(InvalidLevelError);
+    }
+  } else if (newLevel != NormalLevel) {
+    result = make_error_code(InvalidLevelError);
+  }
+  return result;
+}
+
+} // namespace mxc
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mxc/OneWireMaster.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,74 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_mxc_OneWireMaster
+#define MaximInterface_mxc_OneWireMaster
+
+#include <MaximInterface/Links/OneWireMaster.hpp>
+#include <owm.h>
+
+namespace MaximInterface {
+namespace mxc {
+
+/// MCU peripheral 1-Wire master (OWM)
+class OneWireMaster : public MaximInterface::OneWireMaster {
+public:
+  explicit OneWireMaster(mxc_owm_regs_t & owm)
+      : owm(&owm), extStrongPup(false) {}
+
+  void set_mxc_owm(mxc_owm_regs_t & owm) { this->owm = &owm; }
+
+  /// Initialize the hardware interface for use.
+  error_code initialize(const owm_cfg_t & owmCfg,
+                        const sys_cfg_owm_t & sysCfgOwm);
+                        
+  /// Shutdown the hardware interface after use.
+  error_code shutdown();
+
+  virtual error_code reset();
+  virtual error_code touchBitSetLevel(bool & sendRecvBit, Level afterLevel);
+  virtual error_code writeByteSetLevel(uint_least8_t sendByte,
+                                       Level afterLevel);
+  virtual error_code readByteSetLevel(uint_least8_t & recvByte,
+                                      Level afterLevel);
+  virtual error_code setSpeed(Speed newSpeed);
+  virtual error_code setLevel(Level newLevel);
+
+private:
+  mxc_owm_regs_t * owm;
+  bool extStrongPup;
+};
+
+} // namespace mxc
+} // namespace MaximInterface
+
+#endif /* MaximInterface_mxc_OneWireMaster */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mxc/Sleep.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,45 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include "Sleep.hpp"
+
+namespace MaximInterface {
+namespace mxc {
+
+void Sleep::operator()(int ms) const {
+  if (ms > 0) {
+    TMR_Delay(tmr, MSEC(static_cast<unsigned long>(ms)));
+  }
+}
+
+} // namespace mxc
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/mxc/Sleep.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,57 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_mxc_Sleep
+#define MaximInterface_mxc_Sleep
+
+#include <MaximInterface/Links/Sleep.hpp>
+#include <tmr_utils.h>
+
+namespace MaximInterface {
+namespace mxc {
+
+class Sleep : public MaximInterface::Sleep {
+public:
+  explicit Sleep(mxc_tmr_regs_t & tmr) : tmr(&tmr) {}
+
+  void set_mxc_tmr(mxc_tmr_regs_t & tmr) { this->tmr = &tmr; }
+
+  virtual void operator()(int ms) const;
+
+private:
+  mxc_tmr_regs_t * tmr;
+};
+
+} // namespace mxc
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/Ecc256.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,54 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <algorithm>
+#include "Ecc256.hpp"
+
+namespace MaximInterface {
+namespace Ecc256 {
+
+CertificateData createCertificateData(const PublicKey & publicKey,
+                                      const RomId & romId,
+                                      const ManId & manId) {
+  using std::copy;
+
+  CertificateData data;
+  CertificateData::iterator dataIt = data.begin();
+  dataIt = copy(publicKey.x.begin(), publicKey.x.end(), dataIt);
+  dataIt = copy(publicKey.y.begin(), publicKey.y.end(), dataIt);
+  dataIt = copy(romId.begin(), romId.end(), dataIt);
+  copy(manId.begin(), manId.end(), dataIt);
+  return data;
+}
+
+} // namespace Ecc256
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/Ecc256.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,75 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_Ecc256
+#define MaximInterface_Ecc256
+
+#include <stdint.h>
+#include "array.hpp"
+#include "Export.h"
+#include "ManId.hpp"
+#include "RomId.hpp"
+
+namespace MaximInterface {
+namespace Ecc256 {
+
+typedef array<uint_least8_t, 32> Scalar;
+struct Point {
+  Scalar x;
+  Scalar y;
+};
+
+typedef Scalar PrivateKey;
+typedef Point PublicKey;
+struct KeyPair {
+  PrivateKey privateKey;
+  PublicKey publicKey;
+};
+
+struct Signature {
+  Scalar r;
+  Scalar s;
+};
+
+/// Data used to create a device key certificate for ECC-256 authenticators.
+typedef array<uint_least8_t, 2 * Scalar::csize + RomId::csize + ManId::csize>
+    CertificateData;
+
+/// Formats data for creating a device key certificate from the public key,
+/// ROM ID, and MAN ID.
+MaximInterface_EXPORT CertificateData createCertificateData(
+    const PublicKey & publicKey, const RomId & romId, const ManId & manId);
+
+} // namespace Ecc256
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/Error.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,41 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include "Error.hpp"
+
+namespace MaximInterface {
+
+const char * defaultErrorMessage(int condition) {
+  return (condition == 0) ? "Success" : "Unknown Error";
+}
+
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/Error.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,46 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_Error
+#define MaximInterface_Error
+
+#include "Export.h"
+
+namespace MaximInterface {
+
+/// Get the default error message associated with a condition. Typically used
+/// by an error_category when the condition is unknown.
+MaximInterface_EXPORT const char * defaultErrorMessage(int condition);
+
+}
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/Export.h	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,43 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_EXPORT
+    #ifdef _MSC_VER
+        #ifdef _DLL
+            #define MaximInterface_EXPORT __declspec(dllexport)
+        #else
+            #define MaximInterface_EXPORT __declspec(dllimport)
+        #endif /* _DLL */
+    #else
+        #define MaximInterface_EXPORT
+    #endif /* _MSC_VER */
+#endif /* MaximInterface_EXPORT */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/FlagSet.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,188 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_FlagSet
+#define MaximInterface_FlagSet
+
+#include <stddef.h>
+#include <bitset>
+
+namespace MaximInterface {
+
+/// Provides functionality similar to std::bitset except using a bit flag,
+/// typically of an enum type, as the indexer.
+template <typename Flag, size_t flagBits> class FlagSet {
+public:
+  class reference {
+  public:
+    reference(FlagSet & flagSet, Flag flag) : flagSet(&flagSet), flag(flag) {}
+    reference & operator=(bool x) {
+      flagSet->set(flag, x);
+      return *this;
+    }
+    reference & operator=(const reference & x) {
+      return operator=(static_cast<bool>(x));
+    }
+    operator bool() const { return flagSet->test(flag); }
+    bool operator~() const { return reference(*this).flip(); }
+    reference & flip() {
+      *this = !*this;
+      return *this;
+    }
+
+  private:
+    FlagSet * flagSet;
+    Flag flag;
+  };
+
+  FlagSet() : bits() {}
+  FlagSet(unsigned long val) : bits(val) {}
+
+  template <typename CharT, typename Traits, typename Alloc>
+  explicit FlagSet(
+      const std::basic_string<CharT, Traits, Alloc> & str,
+      typename std::basic_string<CharT, Traits, Alloc>::size_type pos = 0,
+      typename std::basic_string<CharT, Traits, Alloc>::size_type n =
+          std::basic_string<CharT, Traits, Alloc>::npos)
+      : bits(str, pos, n) {}
+
+  bool operator==(const FlagSet & rhs) const { return bits == rhs.bits; }
+  bool operator!=(const FlagSet & rhs) const { return !operator==(rhs); }
+
+  // Element access
+  bool operator[](Flag flag) const { return test(flag); }
+  reference operator[](Flag flag) { return reference(*this, flag); }
+  bool test(Flag flag) const { return (bits.to_ulong() & flag) == flag; }
+  bool any() const { return bits.any(); }
+  bool none() const { return bits.none(); }
+  size_t count() const { return bits.count(); }
+
+  // Capacity
+  size_t size() const { return bits.size(); }
+
+  // Modifiers
+  FlagSet & operator&=(const FlagSet & other) {
+    bits &= other.bits;
+    return *this;
+  }
+  FlagSet & operator|=(const FlagSet & other) {
+    bits |= other.bits;
+    return *this;
+  }
+  FlagSet & operator^=(const FlagSet & other) {
+    bits ^= other.bits;
+    return *this;
+  }
+  FlagSet operator~() const { return ~bits; }
+
+  FlagSet & set() {
+    bits.set();
+    return *this;
+  }
+  FlagSet & set(Flag flag, bool value = true) {
+    if (value) {
+      bits |= flag;
+    } else {
+      bits &= ~std::bitset<flagBits>(flag);
+    }
+    return *this;
+  }
+  FlagSet & reset() {
+    bits.reset();
+    return *this;
+  }
+  FlagSet & reset(Flag flag) { return set(flag, false); }
+  FlagSet & flip() {
+    bits.flip();
+    return *this;
+  }
+  FlagSet & flip(Flag flag) {
+    bits ^= flag;
+    return *this;
+  }
+
+  // Conversions
+  template <typename CharT, typename Traits, typename Allocator>
+  std::basic_string<CharT, Traits, Allocator> to_string() const {
+    return bits.template to_string<CharT, Traits, Allocator>();
+  }
+  unsigned long to_ulong() const { return bits.to_ulong(); }
+
+private:
+  std::bitset<flagBits> bits;
+
+  template <typename CharT, typename Traits>
+  friend std::basic_ostream<CharT, Traits> &
+  operator<<(std::basic_ostream<CharT, Traits> & os, const FlagSet & x);
+
+  template <typename CharT, class Traits>
+  friend std::basic_istream<CharT, Traits> &
+  operator>>(std::basic_istream<CharT, Traits> & is, FlagSet & x);
+};
+
+template <typename Flag, size_t flagBits>
+FlagSet<Flag, flagBits> operator&(const FlagSet<Flag, flagBits> & lhs,
+                                  const FlagSet<Flag, flagBits> & rhs) {
+  return FlagSet<Flag, flagBits>(lhs) &= rhs;
+}
+
+template <typename Flag, size_t flagBits>
+FlagSet<Flag, flagBits> operator|(const FlagSet<Flag, flagBits> & lhs,
+                                  const FlagSet<Flag, flagBits> & rhs) {
+  return FlagSet<Flag, flagBits>(lhs) |= rhs;
+}
+
+template <typename Flag, size_t flagBits>
+FlagSet<Flag, flagBits> operator^(const FlagSet<Flag, flagBits> & lhs,
+                                  const FlagSet<Flag, flagBits> & rhs) {
+  return FlagSet<Flag, flagBits>(lhs) ^= rhs;
+}
+
+template <typename CharT, typename Traits, typename Flag, size_t flagBits>
+std::basic_ostream<CharT, Traits> &
+operator<<(std::basic_ostream<CharT, Traits> & os,
+           const FlagSet<Flag, flagBits> & x) {
+  os << x.bits;
+  return os;
+}
+
+template <typename CharT, class Traits, typename Flag, size_t flagBits>
+std::basic_istream<CharT, Traits> &
+operator>>(std::basic_istream<CharT, Traits> & is,
+           FlagSet<Flag, flagBits> & x) {
+  is >> x.bits;
+  return is;
+}
+
+} // namespace MaximInterface
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/Function.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,466 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_Function
+#define MaximInterface_Function
+
+#include <stddef.h>
+#include "type_traits.hpp"
+
+// Include for std::swap.
+#include <algorithm>
+#include <utility>
+
+namespace MaximInterface {
+namespace detail {
+
+// Provides char buffer storage for a given type.
+// Suitability of alignment for type should be verified with alignment_of.
+template <typename Type, size_t TypeSize> union TypeStorage {
+public:
+  operator const Type *() const { return reinterpret_cast<const Type *>(data); }
+
+  operator Type *() {
+    return const_cast<Type *>(
+        static_cast<const Type *>(static_cast<const TypeStorage &>(*this)));
+  }
+
+  const Type & operator*() const { return **this; }
+
+  Type & operator*() {
+    return const_cast<Type &>(
+        static_cast<const TypeStorage &>(*this).operator*());
+  }
+
+  const Type * operator->() const { return *this; }
+
+  Type * operator->() {
+    return const_cast<Type *>(
+        static_cast<const TypeStorage &>(*this).operator->());
+  }
+
+private:
+  char data[TypeSize];
+  long double aligner;
+};
+
+// Computes the internal target size for TypeStorage based on a desired total
+// size. No internal storage will be allocated if the requested size is smaller
+// than the required data elements of TypeWrapper or if the requested size is
+// smaller than minimum size of TypeStorage.
+template <typename Target, size_t totalSize> class TypeWrapperTotalSize {
+private:
+  typedef TypeStorage<Target, 1> MinSizeStorage;
+  static const size_t otherDataSize = sizeof(Target *);
+  // Round down to be a multiple of alignment_of<MinSizeTargetStorage>::value.
+  static const size_t internalTargetRawSize =
+      (totalSize - otherDataSize) / alignment_of<MinSizeStorage>::value *
+      alignment_of<MinSizeStorage>::value;
+
+public:
+  // Use internal storage if internalTargetRawSize is valid and at least as
+  // large as the minimum size of TypeStorage.
+  static const size_t internalTargetSize =
+      ((totalSize > otherDataSize) &&
+       (internalTargetRawSize >= sizeof(MinSizeStorage)))
+          ? internalTargetRawSize
+          : 0;
+};
+
+// Basic type erasure implementation with small object optimization.
+template <typename Target, template <typename> class TargetAdapter,
+          size_t internalTargetSize =
+              TypeWrapperTotalSize<Target, 32>::internalTargetSize>
+class TypeWrapper {
+private:
+  typedef TypeStorage<Target, internalTargetSize> TargetStorage;
+
+public:
+  TypeWrapper() : currentTarget(NULL) {}
+
+  TypeWrapper(const TypeWrapper & other) {
+    if (other.currentTarget == other.internalTarget) {
+      other.currentTarget->clone(internalTarget);
+      currentTarget = internalTarget;
+    } else if (other.currentTarget) {
+      currentTarget = other.currentTarget->clone();
+    } else {
+      currentTarget = NULL;
+    }
+  }
+
+  template <typename Source> TypeWrapper(Source source) {
+    if (sizeof(TargetAdapter<Source>) <= internalTargetSize &&
+        alignment_of<TargetAdapter<Source> >::value <=
+            alignment_of<TargetStorage>::value) {
+      new (internalTarget) TargetAdapter<Source>(source);
+      currentTarget = internalTarget;
+    } else {
+      currentTarget = new TargetAdapter<Source>(source);
+    }
+  }
+
+  ~TypeWrapper() {
+    if (currentTarget == internalTarget) {
+      currentTarget->~Target();
+    } else {
+      delete currentTarget;
+    }
+  }
+
+  const TypeWrapper & operator=(const TypeWrapper & rhs) {
+    TypeWrapper(rhs).swap(*this);
+    return *this;
+  }
+
+  template <typename Source> const TypeWrapper & operator=(Source source) {
+    TypeWrapper(source).swap(*this);
+    return *this;
+  }
+
+  void clear() { TypeWrapper().swap(*this); }
+
+  void swap(TypeWrapper & other) {
+    if (this == &other) {
+      return;
+    }
+
+    if (currentTarget == internalTarget &&
+        other.currentTarget == other.internalTarget) {
+      TargetStorage temp;
+      currentTarget->clone(temp);
+      currentTarget->~Target();
+      currentTarget = NULL;
+      other.currentTarget->clone(internalTarget);
+      other.currentTarget->~Target();
+      other.currentTarget = NULL;
+      currentTarget = internalTarget;
+      temp->clone(other.internalTarget);
+      temp->~Target();
+      other.currentTarget = other.internalTarget;
+    } else if (currentTarget == internalTarget) {
+      currentTarget->clone(other.internalTarget);
+      currentTarget->~Target();
+      currentTarget = other.currentTarget;
+      other.currentTarget = other.internalTarget;
+    } else if (other.currentTarget == other.internalTarget) {
+      other.currentTarget->clone(internalTarget);
+      other.currentTarget->~Target();
+      other.currentTarget = currentTarget;
+      currentTarget = internalTarget;
+    } else {
+      using std::swap;
+      swap(currentTarget, other.currentTarget);
+    }
+  }
+
+  const Target * target() const { return currentTarget; }
+
+private:
+  TargetStorage internalTarget;
+  Target * currentTarget;
+};
+
+// TypeWrapper specialization with no internal storage space.
+template <typename Target, template <typename> class TargetAdapter>
+class TypeWrapper<Target, TargetAdapter, 0> {
+public:
+  TypeWrapper() : currentTarget(NULL) {}
+
+  TypeWrapper(const TypeWrapper & other) {
+    if (other.currentTarget) {
+      currentTarget = other.currentTarget->clone();
+    } else {
+      currentTarget = NULL;
+    }
+  }
+
+  template <typename Source>
+  TypeWrapper(Source source)
+      : currentTarget(new TargetAdapter<Source>(source)) {}
+
+  ~TypeWrapper() { delete currentTarget; }
+
+  const TypeWrapper & operator=(const TypeWrapper & rhs) {
+    TypeWrapper(rhs).swap(*this);
+    return *this;
+  }
+
+  template <typename Source> const TypeWrapper & operator=(Source source) {
+    TypeWrapper(source).swap(*this);
+    return *this;
+  }
+
+  void clear() { TypeWrapper().swap(*this); }
+
+  void swap(TypeWrapper & other) {
+    using std::swap;
+    swap(currentTarget, other.currentTarget);
+  }
+
+  const Target * target() const { return currentTarget; }
+
+private:
+  Target * currentTarget;
+};
+
+} // namespace detail
+
+// Function wrapper similar to std::function for 0-2 argument functions.
+template <typename> class Function;
+
+// Function implementation for zero argument functions.
+template <typename ResultType> class Function<ResultType()> {
+public:
+  typedef ResultType result_type;
+
+  Function(ResultType (*func)() = NULL) : callableWrapper() {
+    if (func) {
+      callableWrapper = func;
+    }
+  }
+
+  template <typename F> Function(F func) : callableWrapper(func) {}
+
+  const Function & operator=(ResultType (*func)()) {
+    if (func) {
+      callableWrapper = func;
+    } else {
+      callableWrapper.clear();
+    }
+    return *this;
+  }
+
+  template <typename F> const Function & operator=(F func) {
+    callableWrapper = func;
+    return *this;
+  }
+
+  void swap(Function & other) { callableWrapper.swap(other.callableWrapper); }
+
+  operator bool() const { return callableWrapper.target() != NULL; }
+
+  ResultType operator()() const {
+    return callableWrapper.target() ? (*callableWrapper.target())()
+                                    : ResultType();
+  }
+
+private:
+  class Callable {
+  public:
+    virtual ~Callable() {}
+    virtual ResultType operator()() const = 0;
+    virtual Callable * clone() const = 0;
+    virtual void clone(void * buffer) const = 0;
+  };
+
+  template <typename F> class CallableAdapter : public Callable {
+  public:
+    CallableAdapter(F func) : func(func) {}
+
+    virtual ResultType operator()() const { return func(); }
+
+    virtual Callable * clone() const { return new CallableAdapter(*this); }
+
+    virtual void clone(void * buffer) const {
+      new (buffer) CallableAdapter(*this);
+    }
+
+  private:
+    F func;
+  };
+
+  detail::TypeWrapper<Callable, CallableAdapter> callableWrapper;
+};
+
+template <typename ResultType>
+inline void swap(Function<ResultType()> & lhs, Function<ResultType()> & rhs) {
+  lhs.swap(rhs);
+}
+
+// Function implementation for one argument functions.
+template <typename ArgumentType, typename ResultType>
+class Function<ResultType(ArgumentType)> {
+public:
+  typedef ArgumentType argument_type;
+  typedef ResultType result_type;
+
+  Function(ResultType (*func)(ArgumentType) = NULL) : callableWrapper() {
+    if (func) {
+      callableWrapper = func;
+    }
+  }
+
+  template <typename F> Function(F func) : callableWrapper(func) {}
+
+  const Function & operator=(ResultType (*func)(ArgumentType)) {
+    if (func) {
+      callableWrapper = func;
+    } else {
+      callableWrapper.clear();
+    }
+    return *this;
+  }
+
+  template <typename F> const Function & operator=(F func) {
+    callableWrapper = func;
+    return *this;
+  }
+
+  void swap(Function & other) { callableWrapper.swap(other.callableWrapper); }
+
+  operator bool() const { return callableWrapper.target() != NULL; }
+
+  ResultType operator()(ArgumentType arg) const {
+    return callableWrapper.target() ? (*callableWrapper.target())(arg)
+                                    : ResultType();
+  }
+
+private:
+  class Callable {
+  public:
+    virtual ~Callable() {}
+    virtual ResultType operator()(ArgumentType) const = 0;
+    virtual Callable * clone() const = 0;
+    virtual void clone(void * buffer) const = 0;
+  };
+
+  template <typename F> class CallableAdapter : public Callable {
+  public:
+    CallableAdapter(F func) : func(func) {}
+
+    virtual ResultType operator()(ArgumentType arg) const { return func(arg); }
+
+    virtual Callable * clone() const { return new CallableAdapter(*this); }
+
+    virtual void clone(void * buffer) const {
+      new (buffer) CallableAdapter(*this);
+    }
+
+  private:
+    F func;
+  };
+
+  detail::TypeWrapper<Callable, CallableAdapter> callableWrapper;
+};
+
+template <typename ArgumentType, typename ResultType>
+inline void swap(Function<ResultType(ArgumentType)> & lhs,
+                 Function<ResultType(ArgumentType)> & rhs) {
+  lhs.swap(rhs);
+}
+
+// Function implementation for two argument functions.
+template <typename FirstArgumentType, typename SecondArgumentType,
+          typename ResultType>
+class Function<ResultType(FirstArgumentType, SecondArgumentType)> {
+public:
+  typedef FirstArgumentType first_argument_type;
+  typedef SecondArgumentType second_argument_type;
+  typedef ResultType result_type;
+
+  Function(ResultType (*func)(FirstArgumentType, SecondArgumentType) = NULL)
+      : callableWrapper() {
+    if (func) {
+      callableWrapper = func;
+    }
+  }
+
+  template <typename F> Function(F func) : callableWrapper(func) {}
+
+  const Function & operator=(ResultType (*func)(FirstArgumentType,
+                                                SecondArgumentType)) {
+    if (func) {
+      callableWrapper = func;
+    } else {
+      callableWrapper.clear();
+    }
+    return *this;
+  }
+
+  template <typename F> const Function & operator=(F func) {
+    callableWrapper = func;
+    return *this;
+  }
+
+  void swap(Function & other) { callableWrapper.swap(other.callableWrapper); }
+
+  operator bool() const { return callableWrapper.target() != NULL; }
+
+  ResultType operator()(FirstArgumentType arg1, SecondArgumentType arg2) const {
+    return callableWrapper.target() ? (*callableWrapper.target())(arg1, arg2)
+                                    : ResultType();
+  }
+
+private:
+  class Callable {
+  public:
+    virtual ~Callable() {}
+    virtual ResultType operator()(FirstArgumentType,
+                                  SecondArgumentType) const = 0;
+    virtual Callable * clone() const = 0;
+    virtual void clone(void * buffer) const = 0;
+  };
+
+  template <typename F> class CallableAdapter : public Callable {
+  public:
+    CallableAdapter(F func) : func(func) {}
+
+    virtual ResultType operator()(FirstArgumentType arg1,
+                                  SecondArgumentType arg2) const {
+      return func(arg1, arg2);
+    }
+
+    virtual Callable * clone() const { return new CallableAdapter(*this); }
+
+    virtual void clone(void * buffer) const {
+      new (buffer) CallableAdapter(*this);
+    }
+
+  private:
+    F func;
+  };
+
+  detail::TypeWrapper<Callable, CallableAdapter> callableWrapper;
+};
+
+template <typename FirstArgumentType, typename SecondArgumentType,
+          typename ResultType>
+inline void
+swap(Function<ResultType(FirstArgumentType, SecondArgumentType)> & lhs,
+     Function<ResultType(FirstArgumentType, SecondArgumentType)> & rhs) {
+  lhs.swap(rhs);
+}
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/HexConversions.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,62 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include <cstdio>
+#include "HexConversions.hpp"
+
+namespace MaximInterface {
+
+static const unsigned int charsPerByte = 2;
+
+std::string byteArrayToHexString(const uint_least8_t * byteArray,
+                                 size_t byteArraySize) {
+  std::string hexString;
+  char hexBuf[charsPerByte + 1];
+  for (size_t i = 0; i < byteArraySize; i++) {
+    std::sprintf(hexBuf, "%2.2X", byteArray[i] & 0xFF);
+    hexString.append(hexBuf, charsPerByte);
+  }
+  return hexString;
+}
+
+std::vector<uint_least8_t> hexStringToByteArray(const std::string & hexString) {
+  std::vector<uint_least8_t> byteArray;
+  byteArray.reserve(hexString.size() / charsPerByte + 1);
+  for (std::string::size_type i = 0; i < hexString.size(); i += charsPerByte) {
+    unsigned int byte;
+    std::sscanf(hexString.substr(i, charsPerByte).c_str(), "%2x", &byte);
+    byteArray.push_back(byte);
+  }
+  return byteArray;
+}
+
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/HexConversions.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,54 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_HexConversions
+#define MaximInterface_HexConversions
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string>
+#include <vector>
+#include <MaximInterface/Utilities/Export.h>
+
+namespace MaximInterface {
+
+/// Convert a byte array to a hex string.
+MaximInterface_EXPORT std::string
+byteArrayToHexString(const uint_least8_t * byteArray, size_t byteArraySize);
+
+/// Convert a hex string to a byte array.
+MaximInterface_EXPORT std::vector<uint_least8_t>
+hexStringToByteArray(const std::string & hexString);
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/ManId.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,45 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_ManId
+#define MaximInterface_ManId
+
+#include "array.hpp"
+
+namespace MaximInterface {
+
+/// Standard container for a manufacturer ID.
+typedef array<uint_least8_t, 2> ManId;
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/RomId.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,70 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_RomId
+#define MaximInterface_RomId
+
+#include "array.hpp"
+#include "crc.hpp"
+
+namespace MaximInterface {
+
+/// Standard container for a 1-Wire ROM ID.
+typedef array<uint_least8_t, 8> RomId;
+
+/// @{
+/// Access the Family Code byte.
+inline RomId::value_type familyCode(const RomId & romId) {
+  return romId.front();
+}
+inline void setFamilyCode(RomId & romId, RomId::value_type familyCode) {
+  romId.front() = familyCode;
+}
+/// @}
+
+/// @{
+/// Access the CRC8 byte.
+inline RomId::value_type crc8(const RomId & romId) { return romId.back(); }
+inline void setCrc8(RomId & romId, RomId::value_type crc8) {
+  romId.back() = crc8;
+}
+/// @}
+
+/// Check if the ROM ID is valid (Family Code and CRC8 are both valid).
+/// @returns True if the ROM ID is valid.
+inline bool valid(const RomId & romId) {
+  return calculateCrc8(romId.data(), romId.size() - 1) == crc8(romId);
+}
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/Segment.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,131 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_Segment
+#define MaximInterface_Segment
+
+#include <iterator>
+#include <utility>
+#include "type_traits.hpp"
+
+namespace MaximInterface {
+
+/// Advances a given iterator by a given number of elements with bounds checking.
+/// InputIt must meet the requirements of InputIterator.
+/// @param[in,out] it Iterator to advance. 
+/// @param bound
+/// Past-the-end boundary iterator. If distance is positive, bound must be
+/// reachable by incrementing the given iterator. If distance is negative, bound
+/// must be reachable by decrementing the given iterator.
+/// @param distance
+/// Number of elements to advance the given iterator. If distance is positive,
+/// the given iterator is incremented. If distance is negative, the given
+/// iterator is decremented, and InputIt must meet the requirements of
+/// BidirectionalIterator.
+/// @returns The number of elements that the given iterator was advanced.
+template <typename InputIt>
+typename std::iterator_traits<InputIt>::difference_type checkedAdvance(
+    InputIt & it, const InputIt bound,
+    typename std::iterator_traits<InputIt>::difference_type distance) {
+  typedef
+      typename std::iterator_traits<InputIt>::difference_type difference_type;
+
+  // Use constant-time operations if InputIt is a random access iterator.
+  if (is_same<typename std::iterator_traits<InputIt>::iterator_category,
+              std::random_access_iterator_tag>::value) {
+    const difference_type boundDistance = std::distance(it, bound);
+    if (boundDistance >= 0) {
+      if (distance > boundDistance) {
+        distance = boundDistance;
+      } else if (distance < 0) {
+        distance = 0;
+      }
+    } else {
+      if (distance < boundDistance) {
+        distance = boundDistance;
+      } else if (distance > 0) {
+        distance = 0;
+      }
+    }
+    std::advance(it, distance);
+  } else {
+    const difference_type startingDistance = distance;
+    while (distance != 0 && it != bound) {
+      if (distance > 0) {
+        ++it;
+        --distance;
+      } else {
+        --it;
+        ++distance;
+      }
+    }
+    if (startingDistance > 0) {
+      distance = startingDistance - distance;
+    } else {
+      distance = startingDistance + distance;
+    }
+  }
+  return distance;
+}
+
+/// Locates an iterator sub-range using segment number addressing. Useful for
+/// devices that divide the memory space into uniform chunks such as pages and
+/// segments. ForwardIt must meet the requirements of ForwardIterator.
+/// @param begin Beginning of the input data range.
+/// @param end End of the input data range.
+/// @param segmentSize Number of elements contained in a segment.
+/// @param segmentNum Zero-indexed number of the desired segment.
+/// @returns Pair of iterators representing the sub-range of the segment within
+/// the input range. If the segment does not exist within the input range, both
+/// iterators in the pair are set to the end interator of the input range.
+template <typename ForwardIt, typename Index>
+std::pair<ForwardIt, ForwardIt> createSegment(
+    ForwardIt begin, const ForwardIt end,
+    const typename std::iterator_traits<ForwardIt>::difference_type segmentSize,
+    Index segmentNum) {
+  ForwardIt segmentEnd = begin;
+  typename std::iterator_traits<ForwardIt>::difference_type lastSegmentSize =
+      checkedAdvance(segmentEnd, end, segmentSize);
+  while (segmentNum > 0 && segmentEnd != end) {
+    begin = segmentEnd;
+    lastSegmentSize = checkedAdvance(segmentEnd, end, segmentSize);
+    --segmentNum;
+  }
+  if (segmentNum > 0 || lastSegmentSize != segmentSize) {
+    begin = segmentEnd;
+  }
+  return std::make_pair(begin, segmentEnd);
+}
+
+} // namespace MaximInterface
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/Sha256.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,59 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_Sha256
+#define MaximInterface_Sha256
+
+#include <stdint.h>
+#include "array.hpp"
+
+namespace MaximInterface {
+namespace Sha256 {
+
+/// Container for a SHA-256 hash.
+typedef array<uint_least8_t, 32> Hash;
+
+// Data used by SHA-256 MAC authenticators including DS28E15/22/25 and DS2465.
+
+/// Data for Compute Write MAC operation.
+typedef array<uint_least8_t, 20> WriteMacData;
+
+/// Data for the Compute Auth. MAC operation.
+typedef array<uint_least8_t, 76>AuthMacData;
+
+/// Data for the Compute Slave Secret operation.
+typedef array<uint_least8_t, 76> SlaveSecretData;
+
+} // namespace Sha256
+} // namespace MaximInterface
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/Uncopyable.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,50 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_Uncopyable
+#define MaximInterface_Uncopyable
+
+namespace MaximInterface {
+
+class Uncopyable {
+protected:
+  Uncopyable() {}
+  ~Uncopyable() {}
+
+private:
+  Uncopyable(const Uncopyable &);
+  const Uncopyable & operator=(const Uncopyable &);
+};
+
+} // namespace MaximInterface
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/WriteMessage.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,46 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_WriteMessage
+#define MaximInterface_WriteMessage
+
+#include <string>
+#include "Function.hpp"
+
+namespace MaximInterface {
+
+/// Writes a message string to an output.
+typedef Function<void(const std::string &)> WriteMessage;
+
+}
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/array.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,151 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_array
+#define MaximInterface_array
+
+#include <stddef.h>
+#include <stdint.h>
+#include <algorithm>
+#include <iterator>
+
+namespace MaximInterface {
+
+/// Generic array class similar to std::array.
+template <typename T, size_t N> class array {
+public:
+  typedef T value_type;
+  typedef size_t size_type;
+  typedef ptrdiff_t difference_type;
+  typedef value_type & reference;
+  typedef const value_type & const_reference;
+  typedef value_type * pointer;
+  typedef const value_type * const_pointer;
+  typedef pointer iterator;
+  typedef const_pointer const_iterator;
+  typedef std::reverse_iterator<iterator> reverse_iterator;
+  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+  // Element access
+  reference operator[](size_type pos) {
+    return const_cast<reference>(
+        static_cast<const array &>(*this).operator[](pos));
+  }
+  const_reference operator[](size_type pos) const { return _buffer[pos]; }
+  reference front() {
+    return const_cast<reference>(static_cast<const array &>(*this).front());
+  }
+  const_reference front() const { return _buffer[0]; }
+  reference back() {
+    return const_cast<reference>(static_cast<const array &>(*this).back());
+  }
+  const_reference back() const { return _buffer[size() - 1]; }
+  pointer data() {
+    return const_cast<pointer>(static_cast<const array &>(*this).data());
+  }
+  const_pointer data() const { return _buffer; }
+
+  // Iterators
+  iterator begin() {
+    return const_cast<iterator>(static_cast<const array &>(*this).cbegin());
+  }
+  const_iterator begin() const { return cbegin(); }
+  const_iterator cbegin() const { return _buffer; }
+  iterator end() {
+    return const_cast<iterator>(static_cast<const array &>(*this).cend());
+  }
+  const_iterator end() const { return cend(); }
+  const_iterator cend() const { return _buffer + size(); }
+  reverse_iterator rbegin() { return reverse_iterator(end()); }
+  const_reverse_iterator rbegin() const {
+    return const_reverse_iterator(end());
+  }
+  const_reverse_iterator crbegin() const { return rbegin(); }
+  reverse_iterator rend() { return reverse_iterator(begin()); }
+  const_reverse_iterator rend() const {
+    return const_reverse_iterator(begin());
+  }
+  const_reverse_iterator crend() const { return rend(); }
+
+  // Capacity
+  static bool empty() { return size() == 0; }
+  static size_type size() { return N; }
+  static size_type max_size() { return size(); }
+  static const size_type csize =
+      N; ///< Alternative to size() when a constant expression is required.
+
+  // Operations
+  void fill(const_reference value) { std::fill(begin(), end(), value); }
+  void swap(array & other) { std::swap_ranges(begin(), end(), other.begin()); }
+
+  T _buffer[N];
+};
+
+template <typename T, size_t N>
+inline bool operator==(const array<T, N> & lhs, const array<T, N> & rhs) {
+  return std::equal(lhs.begin(), lhs.end(), rhs.begin());
+}
+
+template <typename T, size_t N>
+inline bool operator!=(const array<T, N> & lhs, const array<T, N> & rhs) {
+  return !operator==(lhs, rhs);
+}
+
+template <typename T, size_t N>
+inline bool operator<(const array<T, N> & lhs, const array<T, N> & rhs) {
+  return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(),
+                                      rhs.end());
+}
+
+template <typename T, size_t N>
+inline bool operator>(const array<T, N> & lhs, const array<T, N> & rhs) {
+  return operator<(rhs, lhs);
+}
+
+template <typename T, size_t N>
+inline bool operator<=(const array<T, N> & lhs, const array<T, N> & rhs) {
+  return !operator>(lhs, rhs);
+}
+
+template <typename T, size_t N>
+inline bool operator>=(const array<T, N> & lhs, const array<T, N> & rhs) {
+  return !operator<(lhs, rhs);
+}
+
+template <typename T, size_t N>
+inline void swap(array<T, N> & lhs, array<T, N> & rhs) {
+  lhs.swap(rhs);
+}
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/crc.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,86 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include "crc.hpp"
+
+namespace MaximInterface {
+
+uint_fast8_t calculateCrc8(uint_fast8_t data, uint_fast8_t crc) {
+  // See Application Note 27
+  crc ^= data;
+  crc &= 0xff;
+  for (int i = 0; i < 8; i++) {
+    if (crc & 1) {
+      crc = (crc >> 1) ^ 0x8c;
+    } else {
+      crc = (crc >> 1);
+    }
+  }
+  return crc;
+}
+
+uint_fast8_t calculateCrc8(const uint_least8_t * data, size_t dataLen,
+                           uint_fast8_t crc) {
+  for (size_t i = 0; i < dataLen; i++) {
+    crc = calculateCrc8(data[i], crc);
+  }
+  return crc;
+}
+
+uint_fast16_t calculateCrc16(uint_fast8_t data, uint_fast16_t crc) {
+  const uint_least8_t oddparity[] = {0, 1, 1, 0, 1, 0, 0, 1,
+                                     1, 0, 0, 1, 0, 1, 1, 0};
+
+  uint_fast16_t data16 = (data ^ crc) & 0xff;
+  crc = (crc >> 8) & 0xff;
+
+  if (oddparity[data16 & 0xf] ^ oddparity[data16 >> 4]) {
+    crc ^= 0xc001;
+  }
+
+  data16 <<= 6;
+  crc ^= data16;
+  data16 <<= 1;
+  crc ^= data16;
+
+  return crc;
+}
+
+uint_fast16_t calculateCrc16(const uint_least8_t * data, size_t dataLen,
+                             uint_fast16_t crc) {
+  for (size_t i = 0; i < dataLen; i++) {
+    crc = calculateCrc16(data[i], crc);
+  }
+  return crc;
+}
+
+} // namespace MaximInterface
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/crc.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,77 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_crc
+#define MaximInterface_crc
+
+#include <stddef.h>
+#include <stdint.h>
+#include <MaximInterface/Utilities/Export.h>
+
+namespace MaximInterface {
+
+/// Perform a CRC8 calculation.
+/// @param data Data to pass though the CRC generator.
+/// @param crc Beginning state of the CRC generator.
+/// @returns The calculated CRC8.
+MaximInterface_EXPORT uint_fast8_t calculateCrc8(uint_fast8_t data,
+                                                 uint_fast8_t crc = 0);
+
+/// Perform a CRC8 calculation with variable length data.
+/// @param[in] data Data array to pass through the CRC generator.
+/// @param dataLen Length of the data array to process.
+/// @param crc Beginning state of the CRC generator.
+/// @returns The calculated CRC8.
+MaximInterface_EXPORT uint_fast8_t calculateCrc8(const uint_least8_t * data,
+                                                 size_t dataLen,
+                                                 uint_fast8_t crc = 0);
+
+/// Perform a CRC16 calculation.
+/// @param data Data to pass though the CRC generator.
+/// @param crc Beginning state of the CRC generator.
+/// @returns The calculated CRC16.
+MaximInterface_EXPORT uint_fast16_t calculateCrc16(uint_fast8_t data,
+                                                   uint_fast16_t crc = 0);
+
+/// Perform a CRC16 calculation with variable length data.
+/// @param[in] data Data array to pass through the CRC generator.
+/// @param data_offset Offset of the data array to begin processing.
+/// @param data_len Length of the data array to process.
+/// @param crc Beginning state of the CRC generator.
+/// @returns The calculated CRC16.
+MaximInterface_EXPORT uint_fast16_t calculateCrc16(const uint_least8_t * data,
+                                                   size_t dataLen,
+                                                   uint_fast16_t crc = 0);
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/system_error.cpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,63 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#include "Error.hpp"
+#include "system_error.hpp"
+
+namespace MaximInterface {
+
+error_condition error_category::default_error_condition(int code) const {
+  return error_condition(code, *this);
+}
+
+bool error_category::equivalent(int code,
+                                const error_condition & condition) const {
+  return default_error_condition(code) == condition;
+}
+
+bool error_category::equivalent(const error_code & code, int condition) const {
+  return *this == code.category() && code.value() == condition;
+}
+
+const error_category & system_category() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "system"; }
+
+    virtual std::string message(int condition) const {
+      return defaultErrorMessage(condition);
+    }
+  } instance;
+  return instance;
+}
+
+} // namespace MaximInterface
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/system_error.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,167 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_system_error
+#define MaximInterface_system_error
+
+#include <string>
+#include <MaximInterface/Utilities/Export.h>
+#include "Uncopyable.hpp"
+
+namespace MaximInterface {
+
+class error_condition;
+class error_code;
+
+class error_category : private Uncopyable {
+public:
+  virtual ~error_category() {}
+
+  virtual const char * name() const = 0;
+  MaximInterface_EXPORT virtual error_condition
+  default_error_condition(int code) const;
+  MaximInterface_EXPORT virtual bool
+  equivalent(int code, const error_condition & condition) const;
+  MaximInterface_EXPORT virtual bool equivalent(const error_code & code,
+                                                int condition) const;
+  virtual std::string message(int condition) const = 0;
+};
+inline bool operator==(const error_category & lhs, const error_category & rhs) {
+  return &lhs == &rhs;
+}
+inline bool operator!=(const error_category & lhs, const error_category & rhs) {
+  return !operator==(lhs, rhs);
+}
+inline bool operator<(const error_category & lhs, const error_category & rhs) {
+  return &lhs < &rhs;
+}
+
+MaximInterface_EXPORT const error_category & system_category();
+
+class error_condition {
+public:
+  error_condition() : value_(0), category_(&system_category()) {}
+  error_condition(int value, const error_category & category)
+      : value_(value), category_(&category) {}
+
+  void assign(int value, const error_category & category) {
+    value_ = value;
+    category_ = &category;
+  }
+  void clear() {
+    value_ = 0;
+    category_ = &system_category();
+  }
+  int value() const { return value_; }
+  const error_category & category() const { return *category_; }
+  std::string message() const { return category().message(value()); }
+  operator bool() const { return value() != 0; }
+
+private:
+  int value_;
+  const error_category * category_;
+};
+inline bool operator==(const error_condition & lhs,
+                       const error_condition & rhs) {
+  return (lhs.value() == rhs.value()) && (lhs.category() == rhs.category());
+}
+inline bool operator!=(const error_condition & lhs,
+                       const error_condition & rhs) {
+  return !operator==(lhs, rhs);
+}
+inline bool operator<(const error_condition & lhs,
+                      const error_condition & rhs) {
+  return (lhs.category() < rhs.category()) ||
+         ((lhs.category() == rhs.category()) && (lhs.value() < rhs.value()));
+}
+
+class error_code {
+public:
+  error_code() : value_(0), category_(&system_category()) {}
+  error_code(int value, const error_category & category)
+      : value_(value), category_(&category) {}
+
+  void assign(int value, const error_category & category) {
+    value_ = value;
+    category_ = &category;
+  }
+  void clear() {
+    value_ = 0;
+    category_ = &system_category();
+  }
+  int value() const { return value_; }
+  const error_category & category() const { return *category_; }
+  error_condition default_error_condition() const {
+    return category().default_error_condition(value());
+  }
+  std::string message() const { return category().message(value()); }
+  operator bool() const { return value() != 0; }
+
+private:
+  int value_;
+  const error_category * category_;
+};
+inline bool operator==(const error_code & lhs, const error_code & rhs) {
+  return (lhs.value() == rhs.value()) && (lhs.category() == rhs.category());
+}
+inline bool operator!=(const error_code & lhs, const error_code & rhs) {
+  return !operator==(lhs, rhs);
+}
+inline bool operator<(const error_code & lhs, const error_code & rhs) {
+  return (lhs.category() < rhs.category()) ||
+         ((lhs.category() == rhs.category()) && (lhs.value() < rhs.value()));
+}
+
+template <typename CharT, typename Traits>
+std::basic_ostream<CharT, Traits> &
+operator<<(std::basic_ostream<CharT, Traits> & os, const error_code & ec) {
+  os << ec.category().name() << ':' << ec.value();
+  return os;
+}
+
+inline bool operator==(const error_code & lhs, const error_condition & rhs) {
+  return lhs.category().equivalent(lhs.value(), rhs) ||
+         rhs.category().equivalent(lhs, rhs.value());
+}
+inline bool operator!=(const error_code & lhs, const error_condition & rhs) {
+  return !operator==(lhs, rhs);
+}
+inline bool operator==(const error_condition & lhs, const error_code & rhs) {
+  return operator==(rhs, lhs);
+}
+inline bool operator!=(const error_condition & lhs, const error_code & rhs) {
+  return !operator==(lhs, rhs);
+}
+
+} // namespace MaximInterface
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/type_traits.hpp	Mon Nov 06 14:39:18 2017 -0600
@@ -0,0 +1,77 @@
+/*******************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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 Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+
+#ifndef MaximInterface_type_traits
+#define MaximInterface_type_traits
+
+namespace MaximInterface {
+
+template <typename T, T v> struct integral_constant {
+  static const T value = v;
+  typedef T value_type;
+  typedef integral_constant<T, v> type;
+  operator T() { return v; }
+};
+
+typedef integral_constant<bool, true> true_type;
+typedef integral_constant<bool, false> false_type;
+
+template <typename T, typename U> struct is_same : false_type {};
+template <typename T> struct is_same<T, T> : true_type {};
+
+template <bool B, typename T, typename F> struct conditional {
+  typedef T type;
+};
+template <typename T, typename F> struct conditional<false, T, F> {
+  typedef F type;
+};
+
+template <bool B, typename T = void> struct enable_if {};
+template <typename T> struct enable_if<true, T> { typedef T type; };
+
+namespace detail {
+
+template <typename T> struct alignment_of_helper {
+  char a;
+  T b;
+};
+
+} // namespace detail
+
+template <typename T>
+struct alignment_of
+    : integral_constant<size_t,
+                        sizeof(detail::alignment_of_helper<T>) - sizeof(T)> {};
+
+} // namespace MaximInterface
+
+#endif