Device interface library for multiple platforms including Mbed.

Dependents:   DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#

Maxim Interface is a library framework focused on providing flexible and expressive hardware interfaces. Both communication interfaces such as I2C and 1-Wire and device interfaces such as DS18B20 are supported. Modern C++ concepts are used extensively while keeping compatibility with C++98/C++03 and requiring no external dependencies. The embedded-friendly design does not depend on exceptions or RTTI.

The full version of the project is hosted on GitLab: https://gitlab.com/iabenz/MaximInterface

Files at this revision

API Documentation at this revision

Comitter:
IanBenzMaxim
Date:
Mon Jul 22 11:44:07 2019 -0500
Parent:
6:471901a04573
Child:
8:5ea891c7d1a1
Commit message:
Updated to version 1.9.

Changed in this revision

Devices/DS18B20.cpp Show diff for this revision Revisions of this file
Devices/DS18B20.hpp Show diff for this revision Revisions of this file
Devices/DS1920.cpp Show diff for this revision Revisions of this file
Devices/DS1920.hpp Show diff for this revision Revisions of this file
Devices/DS2413.cpp Show diff for this revision Revisions of this file
Devices/DS2413.hpp Show diff for this revision Revisions of this file
Devices/DS2431.cpp Show diff for this revision Revisions of this file
Devices/DS2431.hpp Show diff for this revision Revisions of this file
Devices/DS2465.cpp Show diff for this revision Revisions of this file
Devices/DS2465.hpp Show diff for this revision Revisions of this file
Devices/DS2480B.cpp Show diff for this revision Revisions of this file
Devices/DS2480B.hpp Show diff for this revision Revisions of this file
Devices/DS2482_DS2484.cpp Show diff for this revision Revisions of this file
Devices/DS2482_DS2484.hpp Show diff for this revision Revisions of this file
Devices/DS28C36_DS2476.cpp Show diff for this revision Revisions of this file
Devices/DS28C36_DS2476.hpp Show diff for this revision Revisions of this file
Devices/DS28E15_22_25.cpp Show diff for this revision Revisions of this file
Devices/DS28E15_22_25.hpp Show diff for this revision Revisions of this file
Devices/DS28E17.cpp Show diff for this revision Revisions of this file
Devices/DS28E17.hpp Show diff for this revision Revisions of this file
Devices/DS28E38.cpp Show diff for this revision Revisions of this file
Devices/DS28E38.hpp Show diff for this revision Revisions of this file
Devices/DS9400.cpp Show diff for this revision Revisions of this file
Devices/DS9400.hpp Show diff for this revision Revisions of this file
Devices/DS9481P_300.cpp Show diff for this revision Revisions of this file
Devices/DS9481P_300.hpp Show diff for this revision Revisions of this file
Links/I2CMaster.cpp Show diff for this revision Revisions of this file
Links/I2CMaster.hpp Show diff for this revision Revisions of this file
Links/I2CMasterDecorator.cpp Show diff for this revision Revisions of this file
Links/I2CMasterDecorator.hpp Show diff for this revision Revisions of this file
Links/LoggingI2CMaster.cpp Show diff for this revision Revisions of this file
Links/LoggingI2CMaster.hpp Show diff for this revision Revisions of this file
Links/LoggingOneWireMaster.cpp Show diff for this revision Revisions of this file
Links/LoggingOneWireMaster.hpp Show diff for this revision Revisions of this file
Links/LoggingSleep.cpp Show diff for this revision Revisions of this file
Links/LoggingSleep.hpp Show diff for this revision Revisions of this file
Links/OneWireMaster.cpp Show diff for this revision Revisions of this file
Links/OneWireMaster.hpp Show diff for this revision Revisions of this file
Links/OneWireMasterDecorator.cpp Show diff for this revision Revisions of this file
Links/OneWireMasterDecorator.hpp Show diff for this revision Revisions of this file
Links/RomCommands.cpp Show diff for this revision Revisions of this file
Links/RomCommands.hpp Show diff for this revision Revisions of this file
Links/RunCommand.cpp Show diff for this revision Revisions of this file
Links/RunCommand.hpp Show diff for this revision Revisions of this file
Links/SelectRom.cpp Show diff for this revision Revisions of this file
Links/SelectRom.hpp Show diff for this revision Revisions of this file
Links/SerialPort.hpp Show diff for this revision Revisions of this file
Links/Sleep.hpp Show diff for this revision Revisions of this file
Links/SleepDecorator.cpp Show diff for this revision Revisions of this file
Links/SleepDecorator.hpp Show diff for this revision Revisions of this file
Links/Uart.cpp Show diff for this revision Revisions of this file
Links/Uart.hpp Show diff for this revision Revisions of this file
MaximInterfaceCore/Algorithm.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/ChangeSizeType.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/Config.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/Ecc256.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/Ecc256.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/Error.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/Error.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/FlagSet.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/Function.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/HexConversions.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/HexConversions.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/I2CMaster.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/I2CMaster.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/I2CMasterDecorator.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/I2CMasterDecorator.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/LoggingI2CMaster.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/LoggingI2CMaster.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/LoggingOneWireMaster.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/LoggingOneWireMaster.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/LoggingSleep.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/LoggingSleep.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/ManId.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/None.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/OneWireMaster.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/OneWireMaster.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/OneWireMasterDecorator.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/OneWireMasterDecorator.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/Optional.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/RomCommands.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/RomCommands.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/RomId.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/RunCommand.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/RunCommand.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/SafeBool.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/Segment.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/SelectRom.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/SelectRom.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/SerialPort.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/Sleep.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/SleepDecorator.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/SleepDecorator.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/Uart.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/Uart.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/Unconstructible.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/Uncopyable.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/WriteMessage.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/array.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/array_span.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/crc.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/crc.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/span.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/system_error.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/system_error.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/type_traits.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/Config.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS18B20.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS18B20.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS1920.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS1920.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS2413.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS2413.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS2431.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS2431.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS2465.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS2465.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS2480B.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS2480B.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS2482_DS2484.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS2482_DS2484.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS28C36_DS2476.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS28C36_DS2476.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS28C39.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS28C39.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS28C40.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS28C40.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS28E15_22_25.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS28E15_22_25.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS28E16.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS28E16.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS28E17.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS28E17.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS28E38.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS28E38.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS28E39.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS28E39.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS28E83_DS28E84.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS28E83_DS28E84.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS9400.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS9400.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS9481P_300.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceDevices/DS9481P_300.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceMbed/I2CMaster.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceMbed/I2CMaster.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceMbed/Sleep.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceMbed/Sleep.hpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceMbed/Uart.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceMbed/Uart.hpp Show annotated file Show diff for this revision Revisions of this file
Platforms/mbed/I2CMaster.cpp Show diff for this revision Revisions of this file
Platforms/mbed/I2CMaster.hpp Show diff for this revision Revisions of this file
Platforms/mbed/Sleep.cpp Show diff for this revision Revisions of this file
Platforms/mbed/Sleep.hpp Show diff for this revision Revisions of this file
Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/GpioOneWireMaster.cpp Show diff for this revision Revisions of this file
Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/GpioOneWireMaster.hpp Show diff for this revision Revisions of this file
Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_ARM_STD/owlink.s Show diff for this revision Revisions of this file
Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_GCC_ARM/owlink.S Show diff for this revision Revisions of this file
Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_IAR/owlink.s Show diff for this revision Revisions of this file
Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/owlink.h Show diff for this revision Revisions of this file
Platforms/mbed/Uart.cpp Show diff for this revision Revisions of this file
Platforms/mbed/Uart.hpp Show diff for this revision Revisions of this file
Utilities/Algorithm.hpp Show diff for this revision Revisions of this file
Utilities/ChangeSizeType.hpp Show diff for this revision Revisions of this file
Utilities/Ecc256.cpp Show diff for this revision Revisions of this file
Utilities/Ecc256.hpp Show diff for this revision Revisions of this file
Utilities/Error.cpp Show diff for this revision Revisions of this file
Utilities/Error.hpp Show diff for this revision Revisions of this file
Utilities/Export.h Show diff for this revision Revisions of this file
Utilities/FlagSet.hpp Show diff for this revision Revisions of this file
Utilities/Function.hpp Show diff for this revision Revisions of this file
Utilities/HexConversions.cpp Show diff for this revision Revisions of this file
Utilities/HexConversions.hpp Show diff for this revision Revisions of this file
Utilities/ManId.hpp Show diff for this revision Revisions of this file
Utilities/RomId.hpp Show diff for this revision Revisions of this file
Utilities/SafeBool.hpp Show diff for this revision Revisions of this file
Utilities/Segment.hpp Show diff for this revision Revisions of this file
Utilities/Sha256.hpp Show diff for this revision Revisions of this file
Utilities/Uncopyable.hpp Show diff for this revision Revisions of this file
Utilities/WriteMessage.hpp Show diff for this revision Revisions of this file
Utilities/array.hpp Show diff for this revision Revisions of this file
Utilities/array_span.hpp Show diff for this revision Revisions of this file
Utilities/crc.cpp Show diff for this revision Revisions of this file
Utilities/crc.hpp Show diff for this revision Revisions of this file
Utilities/optional.hpp Show diff for this revision Revisions of this file
Utilities/span.hpp Show diff for this revision Revisions of this file
Utilities/system_error.cpp Show diff for this revision Revisions of this file
Utilities/system_error.hpp Show diff for this revision Revisions of this file
Utilities/type_traits.hpp Show diff for this revision Revisions of this file
mbed_lib.json Show annotated file Show diff for this revision Revisions of this file
--- a/Devices/DS18B20.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,251 +0,0 @@
-/*******************************************************************************
-* 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 {
-
-const uint_least8_t DS18B20::nineBitResolution;
-const uint_least8_t DS18B20::tenBitResolution;
-const uint_least8_t DS18B20::elevenBitResolution;
-const uint_least8_t DS18B20::twelveBitResolution;
-
-error_code DS18B20::initialize() {
-  Scratchpad::array 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[] = {0x4E, th, tl, res};
-    result = master->writeBlock(sendBlock);
-    if (!result) {
-      resolution = res;
-    }
-  }
-  return result;
-}
-
-error_code DS18B20::readScratchpad(Scratchpad::span scratchpad) {  
-  error_code result = selectRom(*master);
-  if (result) {
-    return result;
-  }
-  result = master->writeByte(0xBE);
-  if (result) {
-    return result;
-  }
-  result = master->readBlock(scratchpad);
-  if (result) {
-    return result;
-  }
-  uint_least8_t receivedCrc;
-  result = master->readByte(receivedCrc);
-  if (result) {
-    return result;
-  }
-  if (receivedCrc == calculateCrc8(scratchpad)) {
-    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->writeByte(0xB4);
-  if (result) {
-    return result;
-  }
-  result = master->touchBit(localPower);
-  return result;
-}
-
-error_code DS18B20::copyScratchpad() {
-  const uint_least8_t copyScratchpadCmd = 0x48;
-  
-  bool hasLocalPower;
-  error_code result = readPowerSupply(hasLocalPower);
-  if (result) {
-    return result;
-  }
-  result = selectRom(*master);
-  if (result) {
-    return result;
-  }
-  if (hasLocalPower) {
-    result = master->writeByte(copyScratchpadCmd);
-    bool recvbit = 0;
-    while (!recvbit && !result) {
-      result = master->touchBit(recvbit);
-    }
-  } else {
-    result = master->writeByteSetLevel(copyScratchpadCmd,
-                                       OneWireMaster::StrongLevel);
-    if (!result) {
-      sleep->invoke(10);
-      result = master->setLevel(OneWireMaster::NormalLevel);
-    }
-  }
-  return result;
-}
-
-error_code DS18B20::convertTemperature() {
-  const uint_least8_t convertTemperatureCmd = 0x44;
-  
-  bool hasLocalPower;
-  error_code result = readPowerSupply(hasLocalPower);
-  if (result) {
-    return result;
-  }
-  result = selectRom(*master);
-  if (result) {
-    return result;
-  }
-  if (hasLocalPower) {
-    result = master->writeByte(convertTemperatureCmd);
-    bool recvbit = 0;
-    while (!result && !recvbit) {
-      result = master->touchBit(recvbit);
-    }
-  } else {
-    result = master->writeByteSetLevel(convertTemperatureCmd,
-                                       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->invoke(sleepTime);
-      result = master->setLevel(OneWireMaster::NormalLevel);
-    }
-  }
-  return result;
-}
-
-error_code DS18B20::recallEeprom() {  
-  error_code result = selectRom(*master);
-  if (!result) {
-    result = master->writeByte(0xB8);
-  }
-  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::array scratchpad;
-  result = ds18b20.readScratchpad(scratchpad);
-  if (result) {
-    return result;
-  }
-
-  const 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
--- a/Devices/DS18B20.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*******************************************************************************
-* 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/array_span.hpp>
-#include <MaximInterface/Utilities/Export.h>
-
-namespace MaximInterface {
-
-/// @brief 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_span<uint_least8_t, 8> Scratchpad;
-
-  DS18B20(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
-      : selectRom(selectRom), master(&master), sleep(&sleep), resolution(0) {}
-
-  void setSleep(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::span 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 ds18b20 Device to read.
-/// @param[out] temperature Temperature in degrees Celsius multiplied by 16.
-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
--- a/Devices/DS1920.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/*******************************************************************************
-* 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 {
-
-error_code DS1920::writeScratchpad(uint_least8_t th, uint_least8_t tl) {  
-  error_code result = selectRom(*master);
-  if (!result) {
-    const uint_least8_t sendBlock[] = {0x4E, th, tl};
-    result = master->writeBlock(sendBlock);
-  }
-  return result;
-}
-
-error_code DS1920::readScratchpad(Scratchpad::span scratchpad) {  
-  error_code result = selectRom(*master);
-  if (!result) {
-    result = master->writeByte(0xBE);
-    if (!result) {
-      result = master->readBlock(scratchpad);
-      if (!result) {
-        uint_least8_t receivedCrc;
-        result = master->readByte(receivedCrc);
-        if (!result && (receivedCrc != calculateCrc8(scratchpad))) {
-          result = make_error_code(CrcError);
-        }
-      }
-    }
-  }
-  return result;
-}
-
-error_code DS1920::copyScratchpad() {  
-  error_code result = selectRom(*master);
-  if (!result) {
-    result = master->writeByteSetLevel(0x48, OneWireMaster::StrongLevel);
-    if (!result) {
-      sleep->invoke(10);
-      result = master->setLevel(OneWireMaster::NormalLevel);
-    }
-  }
-  return result;
-}
-
-error_code DS1920::convertTemperature() {  
-  error_code result = selectRom(*master);
-  if (!result) {
-    result = master->writeByteSetLevel(0x44, OneWireMaster::StrongLevel);
-    if (!result) {
-      sleep->invoke(750);
-      result = master->setLevel(OneWireMaster::NormalLevel);
-    }
-  }
-  return result;
-}
-
-error_code DS1920::recallEeprom() {  
-  error_code result = selectRom(*master);
-  if (!result) {
-    result = master->writeByte(0xB8);
-  }
-  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::array 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
--- a/Devices/DS1920.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/*******************************************************************************
-* 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/array_span.hpp>
-#include <MaximInterface/Utilities/Export.h>
-
-namespace MaximInterface {
-
-/// @brief 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_span<uint_least8_t, 8> Scratchpad;
-
-  DS1920(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
-      : selectRom(selectRom), master(&master), sleep(&sleep) {}
-
-  void setSleep(Sleep & sleep) { this->sleep = &sleep; }
-  
-  void setMaster(OneWireMaster & master) { this->master = &master; }
-  
-  void setSelectRom(const SelectRom & selectRom) {
-    this->selectRom = selectRom;
-  }
-
-  /// @brief 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);
-
-  /// @brief Read Scratchpad Command
-  /// @param[out] scratchpad Contents of scratchpad.
-  MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span scratchpad);
-
-  /// @brief 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();
-
-  /// @brief Convert Temperature Command
-  /// @details This command begins a temperature conversion.
-  MaximInterface_EXPORT error_code convertTemperature();
-
-  /// @brief 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;
-};
-
-/// @brief Reads the current temperature as an integer value.
-/// @param ds1920 Device to read.
-/// @param[out] temperature Temperature in degrees Celsius multiplied by 2.
-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
--- a/Devices/DS2413.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*******************************************************************************
-* 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 = val;
-  }
-  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);
-    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";
-      }
-      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[DS2413::PioAOutputState]) {
-    result =
-        ds2413.writeOutputState(pioAState, status[DS2413::PioBOutputState]);
-  }
-  return result;
-}
-
-error_code writePioBOutputState(DS2413 & ds2413, bool pioBState) {
-  DS2413::Status status;
-  error_code result = ds2413.readStatus(status);
-  if (!result && pioBState != status[DS2413::PioBOutputState]) {
-    result =
-        ds2413.writeOutputState(status[DS2413::PioAOutputState], pioBState);
-  }
-  return result;
-}
-
-} // namespace MaximInterface
--- a/Devices/DS2413.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/*******************************************************************************
-* 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>
-#include <MaximInterface/Utilities/FlagSet.hpp>
-
-namespace MaximInterface {
-
-/// @brief 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 };
-
-  enum StatusFlags {
-    PioAInputState = 0x1,
-    PioAOutputState = 0x2,
-    PioBInputState = 0x4,
-    PioBOutputState = 0x8
-  };
-  typedef FlagSet<StatusFlags, 4> Status;
-
-  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 PIOA.
-MaximInterface_EXPORT error_code writePioAOutputState(DS2413 & ds2413,
-                                                      bool pioAState);
-
-/// Write the output logic state for only PIOB.
-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
--- a/Devices/DS2431.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,176 +0,0 @@
-/*******************************************************************************
-* 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 {
-
-error_code writeMemory(DS2431 & device, DS2431::Address targetAddress,
-                       DS2431::Scratchpad::const_span data) {
-  error_code result = device.writeScratchpad(targetAddress, data);
-  if (result) {
-    return result;
-  }
-  DS2431::Scratchpad::array 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,
-                              span<uint_least8_t> data) const {  
-  error_code result = selectRom(*master);
-  if (result) {
-    return result;
-  }
-  const uint_least8_t sendBlock[] = {0xF0, beginAddress, 0x00};
-  result = master->writeBlock(sendBlock);
-  if (result) {
-    return result;
-  }
-  result = master->readBlock(data);
-  return result;
-}
-
-error_code DS2431::writeScratchpad(Address targetAddress,
-                                   Scratchpad::const_span data) {  
-  error_code result = selectRom(*master);
-  if (result) {
-    return result;
-  }
-  uint_least8_t block[3 + Scratchpad::size] = {0x0F, targetAddress, 0x00};
-  std::copy(data.begin(), data.end(), block + 3);
-  result = master->writeBlock(block);
-  if (result) {
-    return result;
-  }
-  const uint_fast16_t calculatedCrc = calculateCrc16(block) ^ 0xFFFFU;
-  result = master->readBlock(make_span(block, 2));
-  if (result) {
-    return result;
-  }
-  if (calculatedCrc !=
-      ((static_cast<uint_fast16_t>(block[1]) << 8) | block[0])) {
-    result = make_error_code(CrcError);
-  }
-  return result;
-}
-
-error_code DS2431::readScratchpad(Scratchpad::span data,
-                                  uint_least8_t & esByte) {
-  typedef array<uint_least8_t, 6 + Scratchpad::size> Block;
-
-  error_code result = selectRom(*master);
-  if (result) {
-    return result;
-  }
-  Block block = {0xAA};
-  result = master->writeByte(block.front());
-  if (result) {
-    return result;
-  }
-  result = master->readBlock(make_span(block).subspan(1));
-  if (result) {
-    return result;
-  }
-  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(make_span(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 {
-    result = make_error_code(CrcError);
-  }
-  return result;
-}
-
-error_code DS2431::copyScratchpad(Address targetAddress, uint_least8_t esByte) {  
-  error_code result = selectRom(*master);
-  if (result) {
-    return result;
-  }
-  uint_least8_t block[] = {0x55, targetAddress, 0x00};
-  result = master->writeBlock(block);
-  if (result) {
-    return result;
-  }
-  result = master->writeByteSetLevel(esByte, OneWireMaster::StrongLevel);
-  if (result) {
-    return result;
-  }
-  sleep->invoke(10);
-  result = master->setLevel(OneWireMaster::NormalLevel);
-  if (result) {
-    return result;
-  }
-  result = master->readByte(block[0]);
-  if (result) {
-    return result;
-  }
-  if (block[0] != 0xAA) {
-    result = make_error_code(OperationFailure);
-  }
-  return result;
-}
-
-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";        
-      }
-      return defaultErrorMessage(condition);
-    }
-  } instance;
-  return instance;
-}
-
-} // namespace MaximInterface
--- a/Devices/DS2431.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*******************************************************************************
-* 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/array_span.hpp>
-#include <MaximInterface/Utilities/Export.h>
-
-namespace MaximInterface {
-
-/// @brief 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_span<uint_least8_t, 8> Scratchpad;
-  typedef uint_least8_t Address;
-
-  DS2431(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
-      : selectRom(selectRom), master(&master), sleep(&sleep) {}
-
-  void setSleep(Sleep & sleep) { this->sleep = &sleep; }
-  
-  void setMaster(OneWireMaster & master) { this->master = &master; }
-  
-  void setSelectRom(const SelectRom & selectRom) {
-    this->selectRom = selectRom;
-  }
-
-  /// @brief 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.
-  MaximInterface_EXPORT error_code readMemory(Address beginAddress,
-                                              span<uint_least8_t> data) const;
-
-  /// @brief 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,
-                                                   Scratchpad::const_span data);
-
-  /// @brief 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::span data,
-                                                  uint_least8_t & esByte);
-
-  /// @brief 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;
-};
-
-/// @brief
-/// Writes data to EEPROM using Write Scratchpad, Read Scratchpad,
-/// and Copy Scratchpad commands.
-/// @param device Device to write.
-/// @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,
-                                             DS2431::Scratchpad::const_span data);
-
-inline error_code make_error_code(DS2431::ErrorValue e) {
-  return error_code(e, DS2431::errorCategory());
-}
-
-} // namespace MaximInterface
-
-#endif
--- a/Devices/DS2465.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,782 +0,0 @@
-/*******************************************************************************
-* 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;
-
-/// 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;
-
-static const uint_least8_t scratchpad = 0x00;
-static const uint_least8_t commandReg = 0x60;
-
-static const uint_least8_t owTransmitBlockCmd = 0x69;
-
-/// 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 int maxBlockSize = 63;
-
-const int DS2465::memoryPages;
-const int DS2465::segmentsPerPage;
-
-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) {
-    const uint_least8_t command[] = {
-        0x1E, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
-                                              : 0xBF)};
-    result = writeMemory(commandReg, command);
-  }
-  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) {
-    const uint_least8_t command[] = {
-        0x2D, static_cast<uint_least8_t>((regwrite << 7) | (swap << 6) |
-                                         (pageNum << 4) | segmentNum)};
-    result = writeMemory(commandReg, command);
-    if (!result) {
-      sleep->invoke(shaComputationDelayMs);
-    }
-  }
-  return result;
-}
-
-error_code DS2465::computeAuthMac(bool swap, int pageNum,
-                                  PageRegion region) const {
-  error_code result = make_error_code(ArgumentOutOfRangeError);
-  if (pageNum >= 0) {
-    const uint_least8_t command[] = {
-        0x3C, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
-                                              : 0xBF)};
-    result = writeMemory(commandReg, command);
-    if (!result) {
-      sleep->invoke(shaComputationDelayMs * 2);
-    }
-  }
-  return result;
-}
-
-error_code DS2465::computeSlaveSecret(bool swap, int pageNum,
-                                      PageRegion region) {
-  error_code result = make_error_code(ArgumentOutOfRangeError);
-  if (pageNum >= 0) {
-    const uint_least8_t command[] = {
-        0x4B, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
-                                              : 0xBF)};
-    result = writeMemory(commandReg, command);
-    if (!result) {
-      sleep->invoke(shaComputationDelayMs * 2);
-    }
-  }
-  return result;
-}
-
-error_code DS2465::readPage(int pageNum, Page::span data) const {
-  uint_least8_t addr;
-  switch (pageNum) {
-  case 0:
-    addr = 0x80;
-    break;
-  case 1:
-    addr = 0xA0;
-    break;
-  default:
-    return make_error_code(ArgumentOutOfRangeError);
-  }
-  return readMemory(addr, data);
-}
-
-error_code DS2465::writePage(int pageNum, Page::const_span data) {
-  error_code result = writeMemory(scratchpad, data);
-  if (!result) {
-    result = copyScratchpad(false, pageNum, false, 0);
-  }
-  if (!result) {
-    sleep->invoke(eepromPageWriteDelayMs);
-  }
-  return result;
-}
-
-error_code DS2465::writeSegment(int pageNum, int segmentNum,
-                                Segment::const_span data) {
-  error_code result = writeMemory(scratchpad, data);
-  if (!result) {
-    result = copyScratchpad(false, pageNum, true, segmentNum);
-  }
-  if (!result) {
-    sleep->invoke(eepromSegmentWriteDelayMs);
-  }
-  return result;
-}
-
-error_code DS2465::writeMasterSecret(Hash::const_span masterSecret) {
-  error_code result = writeMemory(scratchpad, masterSecret);
-  if (!result) {
-    result = copyScratchpad(true, 0, false, 0);
-  }
-  if (!result) {
-    sleep->invoke(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) {
-    const uint_least8_t command[] = {
-        0x5A,
-        static_cast<uint_least8_t>(destSecret ? 0
-                                              : (0x80 | (pageNum << 4) |
-                                                 (notFull << 3) | segmentNum))};
-    result = writeMemory(commandReg, command);
-  }
-  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
-  return writeConfig(Config(curConfig).setSPU(level == StrongLevel));
-}
-
-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
-  return writeConfig(Config(curConfig).set1WS(newSpeed == OverdriveSpeed));
-}
-
-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[] = {
-      0x78, static_cast<uint_least8_t>(data.writeBit ? 0x80 : 0x00)};
-  error_code result = writeMemory(commandReg, command);
-  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(span<uint_least8_t> recvBuf) {
-  // 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;
-  span<uint_least8_t>::index_type recvIdx = 0;
-  while (recvIdx < recvBuf.size() && !result) {
-    const uint_least8_t command[] = {
-        0xE1,
-        static_cast<uint_least8_t>(std::min<span<uint_least8_t>::index_type>(
-            recvBuf.size() - recvIdx, maxBlockSize))};
-    result = writeMemory(commandReg, command);
-    if (!result) {
-      result = pollBusy();
-    }
-    if (!result) {
-      result = readMemory(scratchpad, recvBuf.subspan(recvIdx, command[1]));
-    }
-    recvIdx += command[1];
-  }
-  return result;
-}
-
-error_code DS2465::writeBlock(span<const uint_least8_t> sendBuf) {
-  error_code result;
-  span<const uint_least8_t>::index_type sendIdx = 0;
-  while (sendIdx < sendBuf.size() && !result) {
-    const uint_least8_t command[] = {
-        owTransmitBlockCmd, static_cast<uint_least8_t>(
-                                std::min<span<const uint_least8_t>::index_type>(
-                                    sendBuf.size() - sendIdx, maxBlockSize))};
-
-    // prefill scratchpad with required data
-    result = writeMemory(scratchpad, sendBuf.subspan(sendIdx, 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);
-    }
-    if (!result) {
-      result = pollBusy();
-    }
-    sendIdx += 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);
-  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;
-  }
-
-  const uint_least8_t command = 0x96;
-  result = writeMemory(commandReg, make_span(&command, 1));
-  if (result) {
-    return result;
-  }
-
-  result = pollBusy();
-  if (result) {
-    return result;
-  }
-
-  result = readMemory(0x62, make_span(&recvByte, 1));
-  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[] = {0xA5, sendByte};
-  result = writeMemory(commandReg, command);
-  if (result) {
-    return 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[] = {
-      0x87, static_cast<uint_least8_t>(sendRecvBit ? 0x80 : 0x00)};
-  result = writeMemory(commandReg, command);
-  if (result) {
-    return result;
-  }
-
-  uint_least8_t status;
-  result = pollBusy(&status);
-  if (!result) {
-    sendRecvBit = ((status & Status_SBR) == Status_SBR);
-  }
-  return result;
-}
-
-error_code DS2465::writeMemory(uint_least8_t addr,
-                               span<const uint_least8_t> buf) 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 = master->start(address_);
-  if (result) {
-    master->stop();
-    return result;
-  }
-  result = master->writeByte(addr);
-  if (result) {
-    master->stop();
-    return result;
-  }
-  result = master->writeBlock(buf);
-  if (result) {
-    master->stop();
-    return result;
-  }
-  result = master->stop();
-  return result;
-}
-
-error_code DS2465::readMemory(uint_least8_t addr,
-                              span<uint_least8_t> buf) 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 = master->start(address_);
-  if (result) {
-    master->stop();
-    return result;
-  }
-  result = master->writeByte(addr);
-  if (result) {
-    master->stop();
-    return result;
-  }
-  result = readMemory(buf);
-  return result;
-}
-
-error_code DS2465::readMemory(span<uint_least8_t> buf) const {
-  error_code result = master->start(address_ | 1);
-  if (result) {
-    master->stop();
-    return result;
-  }
-  result = master->readBlock(I2CMaster::Nack, buf);
-  if (result) {
-    master->stop();
-    return result;
-  }
-  result = master->stop();
-  return result;
-}
-
-error_code DS2465::writeConfig(Config config) {
-  const uint_least8_t configReg = 0x67;
-  uint_least8_t configBuf =
-      ((config.readByte() ^ 0xF) << 4) | config.readByte();
-  error_code result = writeMemory(configReg, make_span(&configBuf, 1));
-  if (!result) {
-    result = readMemory(configReg, make_span(&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 = 0x68;
-    break;
-  case tMSP_STD:
-  case tMSP_OD:
-    addr = 0x69;
-    break;
-  case tW0L_STD:
-  case tW0L_OD:
-    addr = 0x6A;
-    break;
-  case tREC0:
-    addr = 0x6B;
-    break;
-  case RWPU:
-    addr = 0x6C;
-    break;
-  case tW1L_OD:
-    addr = 0x6D;
-    break;
-  }
-
-  uint_least8_t data;
-  error_code result = readMemory(addr, make_span(&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, make_span(&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(make_span(&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 = 0xB4;
-  error_code result = writeMemory(commandReg, make_span(&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 = 0xF0;
-  error_code result = writeMemory(commandReg, make_span(&buf, 1));
-
-  if (!result) {
-    result = readMemory(make_span(&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(AuthenticationData::const_span data) {
-  error_code result = writeMemory(scratchpad, data);
-  if (!result) {
-    result = computeNextMasterSecret(false, 0, FullPage);
-  }
-  return result;
-}
-
-error_code
-DS2465::computeNextMasterSecretWithSwap(AuthenticationData::const_span data,
-                                        int pageNum, PageRegion region) {
-  error_code result = writeMemory(scratchpad, data);
-  if (!result) {
-    result = computeNextMasterSecret(true, pageNum, region);
-  }
-  return result;
-}
-
-error_code DS2465::computeWriteMac(WriteMacData::const_span data) const {
-  error_code result = writeMemory(scratchpad, data);
-  if (!result) {
-    result = computeWriteMac(false, false, 0, 0);
-  }
-  return result;
-}
-
-error_code DS2465::computeWriteMac(WriteMacData::const_span data,
-                                   Hash::span mac) const {
-  error_code result = computeWriteMac(data);
-  if (!result) {
-    result = readMemory(mac);
-  }
-  return result;
-}
-
-error_code
-DS2465::computeAndTransmitWriteMac(WriteMacData::const_span data) const {
-  error_code result = computeWriteMac(data);
-  if (!result) {
-    result = writeMacBlock();
-  }
-  return result;
-}
-
-error_code DS2465::computeWriteMacWithSwap(WriteMacData::const_span data,
-                                           int pageNum, int segmentNum) const {
-  error_code result = writeMemory(scratchpad, data);
-  if (!result) {
-    result = computeWriteMac(false, true, pageNum, segmentNum);
-  }
-  return result;
-}
-
-error_code DS2465::computeWriteMacWithSwap(WriteMacData::const_span data,
-                                           int pageNum, int segmentNum,
-                                           Hash::span mac) const {
-  error_code result = computeWriteMacWithSwap(data, pageNum, segmentNum);
-  if (!result) {
-    result = readMemory(mac);
-  }
-  return result;
-}
-
-error_code
-DS2465::computeAndTransmitWriteMacWithSwap(WriteMacData::const_span data,
-                                           int pageNum, int segmentNum) const {
-  error_code result = computeWriteMacWithSwap(data, pageNum, segmentNum);
-  if (!result) {
-    result = writeMacBlock();
-  }
-  return result;
-}
-
-error_code DS2465::computeSlaveSecret(AuthenticationData::const_span data) {
-  error_code result = writeMemory(scratchpad, data);
-  if (!result) {
-    result = computeSlaveSecret(false, 0, FullPage);
-  }
-  return result;
-}
-
-error_code
-DS2465::computeSlaveSecretWithSwap(AuthenticationData::const_span data,
-                                   int pageNum, PageRegion region) {
-  error_code result = writeMemory(scratchpad, data);
-  if (!result) {
-    result = computeSlaveSecret(true, pageNum, region);
-  }
-  return result;
-}
-
-error_code DS2465::computeAuthMac(AuthenticationData::const_span data) const {
-  error_code result = writeMemory(scratchpad, data);
-  if (!result) {
-    result = computeAuthMac(false, 0, FullPage);
-  }
-  return result;
-}
-
-error_code DS2465::computeAuthMac(AuthenticationData::const_span data,
-                                  Hash::span mac) const {
-  error_code result = computeAuthMac(data);
-  if (!result) {
-    result = readMemory(mac);
-  }
-  return result;
-}
-
-error_code
-DS2465::computeAndTransmitAuthMac(AuthenticationData::const_span data) const {
-  error_code result = computeAuthMac(data);
-  if (!result) {
-    result = writeMacBlock();
-  }
-  return result;
-}
-
-error_code DS2465::computeAuthMacWithSwap(AuthenticationData::const_span data,
-                                          int pageNum,
-                                          PageRegion region) const {
-  error_code result = writeMemory(scratchpad, data);
-  if (!result) {
-    result = computeAuthMac(true, pageNum, region);
-  }
-  return result;
-}
-
-error_code DS2465::computeAuthMacWithSwap(AuthenticationData::const_span data,
-                                          int pageNum, PageRegion region,
-                                          Hash::span mac) const {
-  error_code result = computeAuthMacWithSwap(data, pageNum, region);
-  if (!result) {
-    result = readMemory(mac);
-  }
-  return result;
-}
-
-error_code DS2465::computeAndTransmitAuthMacWithSwap(
-    AuthenticationData::const_span 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
--- a/Devices/DS2465.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,404 +0,0 @@
-/*******************************************************************************
-* 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/array_span.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 };
-
-  /// @brief 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_span<uint_least8_t, 4> Segment;
-
-  /// Holds the contents of a device memory page.
-  typedef array_span<uint_least8_t, 32> Page;
-
-  static const int memoryPages = 2;
-  static const int segmentsPerPage = Page::size / Segment::size;
-
-  /// Represents a DS2465 configuration.
-  class Config {
-  public:
-    /// Default construct with power-on config.
-    explicit Config(uint_least8_t readByte = optionAPU)
-        : readByte_(readByte & 0xF) {}
-
-    /// @name 1WS
-    /// @brief 1-Wire Speed
-    /// @{
-    
-    /// Get 1WS bit.
-    bool get1WS() const { return (readByte_ & option1WS) == option1WS; }
-    
-    /// Set 1WS bit.
-    Config & set1WS(bool new1WS) {
-      if (new1WS) {
-        readByte_ |= option1WS;
-      } else {
-        readByte_ &= ~option1WS;
-      }
-      return *this;
-    }
-    
-    /// @}
-
-    /// @name SPU
-    /// @brief Strong Pullup
-    /// @{
-    
-    /// Get SPU bit.
-    bool getSPU() const { return (readByte_ & optionSPU) == optionSPU; }
-    
-    /// Set SPU bit.
-    Config & setSPU(bool newSPU) {
-      if (newSPU) {
-        readByte_ |= optionSPU;
-      } else {
-        readByte_ &= ~optionSPU;
-      }
-      return *this;
-    }
-    
-    /// @}
-
-    /// @name PDN
-    /// @brief 1-Wire Power Down
-    /// @{
-    
-    /// Get PDN bit.
-    bool getPDN() const { return (readByte_ & optionPDN) == optionPDN; }
-    
-    /// Set PDN bit.
-    Config & setPDN(bool newPDN) {
-      if (newPDN) {
-        readByte_ |= optionPDN;
-      } else {
-        readByte_ &= ~optionPDN;
-      }
-      return *this;
-    }
-    
-    /// @}
-
-    /// @name APU
-    /// @brief Active Pullup
-    /// @{
-    
-    /// Get APU bit.
-    bool getAPU() const { return (readByte_ & optionAPU) == optionAPU; }
-    
-    /// Set APU bit.
-    Config & setAPU(bool newAPU) {
-      if (newAPU) {
-        readByte_ |= optionAPU;
-      } else {
-        readByte_ &= ~optionAPU;
-      }
-      return *this;
-    }
-    
-    /// @}
-
-    /// 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(Sleep & sleep, I2CMaster & master, uint_least8_t address = 0x30)
-      : sleep(&sleep), master(&master), address_(address & 0xFE) {}
-
-  void setSleep(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) { address_ = address & 0xFE; }
-
-  /// Initialize hardware for use.
-  MaximInterface_EXPORT error_code initialize(Config config = Config());
-
-  /// @brief Write a new configuration to the DS2465.
-  /// @param[in] config New configuration to write.
-  MaximInterface_EXPORT error_code writeConfig(Config config);
-
-  /// @brief 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(span<uint_least8_t> recvBuf);
-  
-  MaximInterface_EXPORT virtual error_code
-  writeBlock(span<const uint_least8_t> sendBuf);
-  
-  MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed);
-  
-  /// @copydoc OneWireMaster::setLevel
-  /// @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
-
-  /// @brief Read data from an EEPROM memory page.
-  /// @param pageNum Page number to read from.
-  /// @param[out] data Data that was read.
-  MaximInterface_EXPORT error_code readPage(int pageNum, Page::span data) const;
-
-  /// @brief Write data to an EEPROM memory page.
-  /// @param pageNum Page number to copy to.
-  /// @param data Data to write.
-  MaximInterface_EXPORT error_code writePage(int pageNum,
-                                             Page::const_span data);
-
-  /// @brief Write data to an EEPROM memory segment.
-  /// @param pageNum Page number to copy to.
-  /// @param segmentNum Segment number to copy to.
-  /// @param data Data to write.
-  MaximInterface_EXPORT error_code writeSegment(int pageNum, int segmentNum,
-                                                Segment::const_span data);
-
-  /// Write data to the secret EEPROM memory page.
-  MaximInterface_EXPORT error_code
-  writeMasterSecret(Sha256::Hash::const_span masterSecret);
-
-  /// @brief Compute Next Master Secret.
-  /// @param data Combined data fields for computation.
-  MaximInterface_EXPORT error_code
-  computeNextMasterSecret(Sha256::AuthenticationData::const_span data);
-
-  /// @brief 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(Sha256::AuthenticationData::const_span data,
-                                  int pageNum, PageRegion region);
-
-  /// @brief Compute Write MAC.
-  /// @param data Combined data fields for computation.
-  /// @param[out] mac Computed Write MAC.
-  MaximInterface_EXPORT error_code computeWriteMac(
-      Sha256::WriteMacData::const_span data, Sha256::Hash::span mac) const;
-
-  /// @brief Compute Write MAC.
-  /// @param data Combined data fields for computation.
-  MaximInterface_EXPORT error_code
-  computeAndTransmitWriteMac(Sha256::WriteMacData::const_span data) const;
-
-  /// @brief 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(Sha256::WriteMacData::const_span data, int pageNum,
-                          int segmentNum, Sha256::Hash::span mac) const;
-
-  /// @brief 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(
-      Sha256::WriteMacData::const_span data, int pageNum, int segmentNum) const;
-
-  /// @brief Compute Slave Secret (S-Secret).
-  /// @param data Combined data fields for computation.
-  MaximInterface_EXPORT error_code
-  computeSlaveSecret(Sha256::AuthenticationData::const_span data);
-
-  /// @brief 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(Sha256::AuthenticationData::const_span data,
-                             int pageNum, PageRegion region);
-
-  /// @brief Compute Authentication MAC.
-  /// @param data Combined data fields for computation.
-  /// @param[out] mac Computed Auth MAC.
-  MaximInterface_EXPORT error_code
-  computeAuthMac(Sha256::AuthenticationData::const_span data,
-                 Sha256::Hash::span mac) const;
-
-  /// @brief Compute Authentication MAC.
-  /// @param data Combined data fields for computation.
-  MaximInterface_EXPORT error_code
-  computeAndTransmitAuthMac(Sha256::AuthenticationData::const_span data) const;
-
-  /// @brief 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(
-      Sha256::AuthenticationData::const_span data, int pageNum,
-      PageRegion region, Sha256::Hash::span mac) const;
-
-  /// @brief 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(Sha256::AuthenticationData::const_span data,
-                                    int pageNum, PageRegion region) const;
-
-  MaximInterface_EXPORT static const error_category & errorCategory();
-
-private:
-  const Sleep * sleep;
-  I2CMaster * master;
-  uint_least8_t address_;
-  Config curConfig;
-
-  /// @brief Performs a soft reset on the DS2465.
-  /// @note This is not a 1-Wire Reset.
-  error_code resetDevice();
-
-  /// @brief
-  /// 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;
-
-  /// @brief Ensure that the desired 1-Wire level is set in the configuration.
-  /// @param level Desired 1-Wire level.
-  error_code configureLevel(Level level);
-
-  /// @note Const since only for internal use.
-  error_code writeMemory(uint_least8_t addr,
-                         span<const uint_least8_t> buf) const;
-
-  /// @brief Read memory from the DS2465.
-  /// @param addr Address to begin reading from.
-  /// @param[out] buf Buffer to hold read data.
-  error_code readMemory(uint_least8_t addr, span<uint_least8_t> buf) const;
-
-  /// @brief Read memory from the DS2465 at the current pointer.
-  /// @param[out] buf Buffer to hold read data.
-  error_code readMemory(span<uint_least8_t> buf) const;
-
-  /// Write the last computed MAC to the 1-Wire bus.
-  error_code writeMacBlock() const;
-
-  error_code computeWriteMac(Sha256::WriteMacData::const_span data) const;
-
-  error_code computeWriteMacWithSwap(Sha256::WriteMacData::const_span data,
-                                     int pageNum, int segmentNum) const;
-
-  error_code computeAuthMac(Sha256::AuthenticationData::const_span data) const;
-
-  error_code computeAuthMacWithSwap(Sha256::AuthenticationData::const_span 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
--- a/Devices/DS2480B.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,559 +0,0 @@
-/*******************************************************************************
-* 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
-
-// Baud rate bits
-#define PARMSET_9600 0x00
-#define PARMSET_19200 0x02
-#define PARMSET_57600 0x04
-#define PARMSET_115200 0x06
-
-// DS2480B program voltage available
-#define DS2480BPROG_MASK 0x20
-
-namespace MaximInterface {
-
-error_code DS2480B::initialize() {
-  level = NormalLevel;
-  mode = MODSEL_COMMAND;
-  speed = SPEEDSEL_STD;
-
-  // Send a break to reset the DS2480B.
-  // Switch to lower baud rate to ensure break is longer than 2 ms.
-  error_code result = uart->setBaudRate(4800);
-  if (result) {
-    return result;
-  }
-  result = uart->sendBreak();
-  if (result) {
-    return result;
-  }
-  result = uart->setBaudRate(9600);
-  if (result) {
-    return result;
-  }
-
-  // Wait for master reset.
-  sleep->invoke(1);
-
-  // Flush the read buffer.
-  result = uart->clearReadBuffer();
-  if (result) {
-    return result;
-  }
-
-  // Send the timing byte.
-  result = uart->writeByte(CMD_COMM | FUNCTSEL_RESET | SPEEDSEL_STD);
-  if (result) {
-    return result;
-  }
-
-  // Change the DS2480 baud rate.
-  result = uart->writeByte(CMD_CONFIG | PARMSEL_BAUDRATE | PARMSET_115200);
-  if (result) {
-    return result;
-  }
-
-  // Change our baud rate.
-  result = uart->setBaudRate(115200);
-  if (result) {
-    return result;
-  }
-
-  uint_least8_t response;
-
-  // Verify response.
-  result = uart->readByte(response);
-  if (result) {
-    return result;
-  }
-  if ((response & (PARMSEL_MASK | PARMSET_MASK)) !=
-      (PARMSEL_BAUDRATE | PARMSET_115200)) {
-    return make_error_code(HardwareError);
-  }
-
-  // Set the SPUD time value.
-  result = uart->writeByte(CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite);
-  if (result) {
-    return result;
-  }
-
-  // Verify response.
-  result = uart->readByte(response);
-  if (result) {
-    return result;
-  }
-  if ((response & (PARMSEL_MASK | PARMSET_MASK)) !=
-      (PARMSEL_5VPULSE | PARMSET_infinite)) {
-    return make_error_code(HardwareError);
-  }
-
-  return result;
-}
-
-error_code DS2480B::reset() {
-  if (level != NormalLevel) {
-    return make_error_code(InvalidLevelError);
-  }
-
-  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;
-
-  // Send the packet.
-  error_code result = uart->writeBlock(make_span(packet, packetLen));
-  if (result) {
-    return result;
-  }
-
-  // Read back the response.
-  result = uart->readByte(packet[0]);
-  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) {
-  if (level != NormalLevel) {
-    return make_error_code(InvalidLevelError);
-  }
-
-  uint_least8_t packet[3];
-  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_BIT |
-                        (sendRecvBit ? BITPOL_ONE : BITPOL_ZERO) | speed;
-  switch (afterLevel) {
-  case NormalLevel:
-    break;
-
-  case StrongLevel:
-    // Add the command to begin the pulse.
-    packet[packetLen++] =
-        CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE;
-    break;
-
-  default:
-    return make_error_code(InvalidLevelError);
-  }
-
-  // Send the packet.
-  error_code result = uart->writeBlock(make_span(packet, packetLen));
-  if (result) {
-    return result;
-  }
-
-  // Read back the response.
-  result = uart->readByte(packet[0]);
-  if (result) {
-    return result;
-  }
-
-  // Interpret the response.
-  if ((packet[0] & 0xE0) == 0x80) {
-    sendRecvBit = ((packet[0] & RB_BIT_MASK) == RB_BIT_ONE);
-    level = afterLevel;
-  } else {
-    result = make_error_code(HardwareError);
-  }
-  return result;
-}
-
-error_code DS2480B::writeByteSetLevel(uint_least8_t sendByte,
-                                      Level afterLevel) {
-  if (level != NormalLevel) {
-    return make_error_code(InvalidLevelError);
-  }
-
-  switch (afterLevel) {
-  case NormalLevel:
-    break;
-
-  case StrongLevel:
-    return OneWireMaster::writeByteSetLevel(sendByte, afterLevel);
-
-  default:
-    return make_error_code(InvalidLevelError);
-  }
-
-  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;
-  }
-
-  // Send the packet.
-  error_code result = uart->writeBlock(make_span(packet, packetLen));
-  if (result) {
-    return result;
-  }
-
-  // Read back the response.
-  result = uart->readByte(packet[0]);
-  if (result) {
-    return result;
-  }
-
-  // Interpret the response.
-  if (packet[0] != sendByte) {
-    result = make_error_code(HardwareError);
-  }
-  return result;
-}
-
-error_code DS2480B::readByteSetLevel(uint_least8_t & recvByte,
-                                     Level afterLevel) {
-  if (level != NormalLevel) {
-    return make_error_code(InvalidLevelError);
-  }
-
-  switch (afterLevel) {
-  case NormalLevel:
-    break;
-
-  case StrongLevel:
-    return OneWireMaster::readByteSetLevel(recvByte, afterLevel);
-
-  default:
-    return make_error_code(InvalidLevelError);
-  }
-
-  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;
-
-  // Send the packet.
-  error_code result = uart->writeBlock(make_span(packet, packetLen));
-  if (result) {
-    return result;
-  }
-
-  // Read back the response.
-  result = uart->readByte(recvByte);
-  return result;
-}
-
-error_code DS2480B::setSpeed(Speed newSpeed) {
-  uint_least8_t newSpeedByte;
-  switch (newSpeed) {
-  case OverdriveSpeed:
-    newSpeedByte = SPEEDSEL_OD;
-    break;
-
-  case StandardSpeed:
-    newSpeedByte = SPEEDSEL_STD;
-    break;
-
-  default:
-    return make_error_code(InvalidSpeedError);
-  }
-  if (speed == newSpeedByte) {
-    return error_code();
-  }
-  speed = newSpeedByte;
-
-  uint_least8_t packet[2];
-  int packetLen = 0;
-
-  // Check for correct mode.
-  if (mode != MODSEL_COMMAND) {
-    mode = MODSEL_COMMAND;
-    packet[packetLen++] = MODE_COMMAND;
-  }
-
-  // Change DS2480 speed.
-  packet[packetLen++] = CMD_COMM | FUNCTSEL_SEARCHOFF | speed;
-
-  // Send the packet.
-  return uart->writeBlock(make_span(packet, packetLen));
-}
-
-error_code DS2480B::setLevel(Level newLevel) {
-  if (level == newLevel) {
-    return error_code();
-  }
-
-  uint_least8_t packet[2];
-  int packetLen = 0;
-
-  switch (newLevel) {
-  case NormalLevel:
-    // Stop pulse command.
-    packet[packetLen++] = MODE_STOP_PULSE;
-    break;
-
-  case StrongLevel:
-    // Check for correct mode.
-    if (mode != MODSEL_COMMAND) {
-      mode = MODSEL_COMMAND;
-      packet[packetLen++] = MODE_COMMAND;
-    }
-
-    // Add the command to begin the pulse.
-    packet[packetLen++] =
-        CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE;
-    break;
-
-  default:
-    return make_error_code(InvalidLevelError);
-  }
-
-  // Send the packet.
-  error_code result = uart->writeBlock(make_span(packet, packetLen));
-  if (result) {
-    return result;
-  }
-
-  if (newLevel == NormalLevel) {
-    // Read back the response.
-    result = uart->readByte(packet[0]);
-    if (result) {
-      return result;
-    }
-
-    // Interpret the response.
-    if ((packet[0] & 0xE0) != 0xE0) {
-      return make_error_code(HardwareError);
-    }
-  }
-
-  level = newLevel;
-  return result;
-}
-
-error_code DS2480B::sendCommand(uint_least8_t command) {
-  uint_least8_t packet[2];
-  int packetLen = 0;
-
-  // Check for correct mode.
-  if (mode != MODSEL_COMMAND) {
-    mode = MODSEL_COMMAND;
-    packet[packetLen++] = MODE_COMMAND;
-  }
-
-  // Add command.
-  packet[packetLen++] = command;
-
-  // Send the packet.
-  return uart->writeBlock(make_span(packet, packetLen));
-}
-
-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
--- a/Devices/DS2480B.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*******************************************************************************
-* 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(Sleep & sleep, Uart & uart) : sleep(&sleep), uart(&uart) {}
-
-  void setSleep(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();
-
-protected:
-  MaximInterface_EXPORT error_code sendCommand(uint_least8_t command);
-
-private:
-  const Sleep * sleep;
-  Uart * uart;
-
-  Level level;
-  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
--- a/Devices/DS2482_DS2484.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,424 +0,0 @@
-/*******************************************************************************
-* 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 {
-
-// 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) {
-  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
-
-  error_code result = sendCommand(0xF0);
-  if (result) {
-    return result;
-  }
-
-  uint_least8_t buf;
-  result = readRegister(buf);
-  if (result) {
-    return result;
-  }
-
-  if ((buf & 0xF7) != 0x10) {
-    return make_error_code(HardwareError);
-  }
-
-  // Do a command to get 1-Wire master reset out of holding state.
-  reset();
-
-  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(0x78, data.writeBit ? 0x80 : 0x00);
-  if (!result) {
-    uint_least8_t status;
-    result = pollBusy(&status);
-    if (!result) {
-      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(0xB4);
-  if (result) {
-    return result;
-  }
-
-  uint_least8_t buf;
-  result = pollBusy(&buf);
-  if (result) {
-    return 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) {
-    return result;
-  }
-
-  result = sendCommand(0x87, sendRecvBit ? 0x80 : 0x00);
-  if (result) {
-    return result;
-  }
-
-  uint_least8_t status;
-  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(0xA5, sendByte);
-  if (result) {
-    return 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(0x96);
-  if (result) {
-    return result;
-  }
-
-  result = pollBusy();
-  if (result) {
-    return result;
-  }
-
-  result = readRegister(0xE1, recvByte);
-  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
-  return writeConfig(Config(curConfig).set1WS(newSpeed == OverdriveSpeed));
-}
-
-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(0xD2, configBuf);
-  if (!result) {
-    result = readRegister(0xC3, 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(0xE1, reg);
-  if (!result) {
-    result = readRegister(buf);
-  }
-  return result;
-}
-
-error_code DS2482_DS2484::readRegister(uint_least8_t & buf) const {
-  return master->readPacket(address_, make_span(&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
-  return writeConfig(Config(curConfig).setSPU(level == StrongLevel));
-}
-
-error_code DS2482_DS2484::sendCommand(uint_least8_t cmd) const {
-  return master->writePacket(address_, make_span(&cmd, 1));
-}
-
-error_code DS2482_DS2484::sendCommand(uint_least8_t cmd,
-                                      uint_least8_t param) const {
-  uint_least8_t buf[] = {cmd, param};
-  return master->writePacket(address_, buf);
-}
-
-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(0xC3, 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(0xC3, (param << 4) | val);
-  if (result) {
-    return result;
-  }
-
-  uint_least8_t portConfig = val + 1;
-  for (int reads = -1; reads < param; ++reads) {
-    result = readRegister(portConfig);
-    if (result) {
-      return result;
-    }
-  }
-  if (val != portConfig) {
-    result = make_error_code(HardwareError);
-  }
-
-  return result;
-}
-
-} // namespace MaximInterface
--- a/Devices/DS2482_DS2484.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,261 +0,0 @@
-/*******************************************************************************
-* 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) {}
-
-    /// @name 1WS
-    /// @brief 1-Wire Speed
-    /// @{
-    
-    /// Get 1WS bit.
-    bool get1WS() const { return (readByte_ & option1WS) == option1WS; }
-    
-    /// Set 1WS bit.
-    Config & set1WS(bool new1WS) {
-      if (new1WS) {
-        readByte_ |= option1WS;
-      } else {
-        readByte_ &= ~option1WS;
-      }
-      return *this;
-    }
-    
-    /// @}
-
-    /// @name SPU
-    /// @brief Strong Pullup
-    /// @{
-    
-    /// Get SPU bit.
-    bool getSPU() const { return (readByte_ & optionSPU) == optionSPU; }
-    
-    /// Set SPU bit.
-    Config & setSPU(bool newSPU) {
-      if (newSPU) {
-        readByte_ |= optionSPU;
-      } else {
-        readByte_ &= ~optionSPU;
-      }
-      return *this;
-    }
-    
-    /// @}
-
-    /// @name PDN
-    /// @brief 1-Wire Power Down
-    /// @{
-    
-    /// Get PDN bit.
-    bool getPDN() const { return (readByte_ & optionPDN) == optionPDN; }
-    
-    /// Set PDN bit.
-    Config & setPDN(bool newPDN) {
-      if (newPDN) {
-        readByte_ |= optionPDN;
-      } else {
-        readByte_ &= ~optionPDN;
-      }
-      return *this;
-    }
-    
-    /// @}
-
-    /// @name APU
-    /// @brief Active Pullup
-    /// @{
-    
-    /// Get APU bit.
-    bool getAPU() const { return (readByte_ & optionAPU) == optionAPU; }
-    
-    /// Set APU bit.
-    Config & setAPU(bool newAPU) {
-      if (newAPU) {
-        readByte_ |= optionAPU;
-      } else {
-        readByte_ &= ~optionAPU;
-      }
-      return *this;
-    }
-    
-    /// @}
-
-    /// 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 setMaster(I2CMaster & master) { this->master = &master; }
-  
-  uint_least8_t address() const { return address_; }
-  
-  void setAddress(uint_least8_t address) { address_ = address; }
-
-  /// Initialize hardware for use.
-  MaximInterface_EXPORT error_code initialize(Config config = Config());
-
-  /// @brief Write a new configuration to the device.
-  /// @param[in] config New configuration to write.
-  MaximInterface_EXPORT error_code writeConfig(Config config);
-
-  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 & master, uint_least8_t address)
-      : master(&master), address_(address) {}
-
-  /// @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;
-
-  /// @brief 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;
-
-  /// @brief Reads the current register from the device.
-  /// @param[out] buf Buffer to hold read data.
-  error_code readRegister(uint_least8_t & buf) const;
-
-private:
-  /// @brief Performs a soft reset on the device.
-  /// @note This is not a 1-Wire Reset.
-  error_code resetDevice();
-
-  /// @brief
-  /// 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);
-
-  /// @brief Ensure that the desired 1-Wire level is set in the configuration.
-  /// @param level Desired 1-Wire level.
-  error_code configureLevel(Level level);
-
-  I2CMaster * master;
-  uint_least8_t address_;
-  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) {}
-
-  /// @brief 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:
-  /// @brief 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) {}
-
-  /// @brief 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
--- a/Devices/DS28C36_DS2476.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,724 +0,0 @@
-/*******************************************************************************
-* 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/I2CMaster.hpp>
-#include <MaximInterface/Utilities/Error.hpp>
-#include <MaximInterface/Utilities/RomId.hpp>
-#include "DS28C36_DS2476.hpp"
-
-namespace MaximInterface {
-
-using namespace Ecc256;
-using std::copy;
-
-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;
-}
-
-const int DS28C36::publicKeyAxPage;
-const int DS28C36::publicKeyAyPage;
-const int DS28C36::publicKeyBxPage;
-const int DS28C36::publicKeyByPage;
-const int DS28C36::publicKeyCxPage;
-const int DS28C36::publicKeyCyPage;
-const int DS28C36::privateKeyAPage;
-const int DS28C36::privateKeyBPage;
-const int DS28C36::privateKeyCPage;
-const int DS28C36::secretAPage;
-const int DS28C36::secretBPage;
-const int DS28C36::decrementCounterPage;
-const int DS28C36::romOptionsPage;
-const int DS28C36::gpioControlPage;
-const int DS28C36::publicKeySxPage;
-const int DS28C36::publicKeySyPage;
-const int DS28C36::memoryPages;
-
-error_code DS28C36::writeMemory(int pageNum, Page::const_span page) {
-  if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
-  }
-
-  uint_least8_t buffer[1 + Page::size];
-  buffer[0] = pageNum;
-  copy(page.begin(), page.end(), buffer + 1);
-  error_code result = writeCommand(0x96, buffer);
-  if (!result) {
-    sleep(writeMemoryTimeMs);
-    result = readFixedLengthResponse(make_span(buffer, 1));
-    if (!result) {
-      result = convertResultByte(buffer[0]);
-    }
-  }
-  return result;
-}
-
-error_code DS28C36::readMemory(int pageNum, Page::span page) {
-  if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
-  }
-
-  const uint_least8_t parameter = pageNum;
-  error_code result = writeCommand(0x69, make_span(&parameter, 1));
-  if (!result) {
-    sleep(readMemoryTimeMs);
-    array<uint_least8_t, 1 + Page::size> response;
-    result = readFixedLengthResponse(response);
-    if (!result) {
-      result = convertResultByte(response[0]);
-      copy(response.begin() + 1, response.end(), page.begin());
-    }
-  }
-  return result;
-}
-
-error_code DS28C36::writeBuffer(span<const uint_least8_t> data) {
-  return writeCommand(0x87, data);
-}
-
-error_code DS28C36::readBuffer(std::vector<uint_least8_t> & data) {
-  error_code result = writeCommand(0x5A);
-  if (!result) {
-    data.resize(80);
-    span<uint_least8_t> dataSpan(data);
-    result = readVariableLengthResponse(dataSpan);
-    if (result) {
-      data.clear();
-    } else {
-      data.resize(dataSpan.size());
-    }
-  }
-  return result;
-}
-
-error_code DS28C36::readPageProtection(int pageNum,
-                                       PageProtection & protection) {
-  if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
-  }
-
-  uint_least8_t buffer = pageNum;
-  error_code result = writeCommand(0xAA, make_span(&buffer, 1));
-  if (!result) {
-    sleep(readMemoryTimeMs);
-    result = readFixedLengthResponse(make_span(&buffer, 1));
-    if (!result) {
-      protection = buffer;
-    }
-  }
-  return result;
-}
-
-error_code DS28C36::setPageProtection(int pageNum,
-                                      const PageProtection & protection) {
-  if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
-  }
-
-  uint_least8_t buffer[] = {static_cast<uint_least8_t>(pageNum),
-                            static_cast<uint_least8_t>(protection.to_ulong())};
-  error_code result = writeCommand(0xC3, buffer);
-  if (!result) {
-    sleep(writeMemoryTimeMs);
-    result = readFixedLengthResponse(make_span(buffer, 1));
-    if (!result) {
-      result = convertResultByte(buffer[0]);
-    }
-  }
-  return result;
-}
-
-error_code DS28C36::decrementCounter() {
-  error_code result = writeCommand(0xC9);
-  if (!result) {
-    sleep(writeMemoryTimeMs);
-    uint_least8_t response;
-    result = readFixedLengthResponse(make_span(&response, 1));
-    if (!result) {
-      result = convertResultByte(response);
-    }
-  }
-  return result;
-}
-
-error_code DS28C36::readRng(span<uint_least8_t> data) {
-  if ((data.size() < 1) || (data.size() > 64)) {
-    return make_error_code(InvalidParameterError);
-  }
-
-  data[0] = static_cast<uint_least8_t>(data.size() - 1);
-  error_code result = writeCommand(0xD2, data.first(1));
-  if (!result) {
-    sleep(sha256ComputationTimeMs);
-    result = readFixedLengthResponse(data);
-  }
-  return result;
-}
-
-error_code DS28C36::encryptedReadMemory(int pageNum, SecretNum secretNum,
-                                        EncryptionChallenge::span challenge,
-                                        Page::span data) {
-  if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
-  }
-
-  const uint_least8_t parameter = (secretNum << 6) | pageNum;
-  error_code result = writeCommand(0x4B, make_span(&parameter, 1));
-  if (!result) {
-    sleep(readMemoryTimeMs + sha256ComputationTimeMs);
-    uint_least8_t response[1 + EncryptionChallenge::size + Page::size];
-    result = readFixedLengthResponse(response);
-    if (!result) {
-      result = convertResultByte(response[0]);
-      const uint_least8_t * begin = response + 1;
-      const uint_least8_t * end = begin + challenge.size();
-      copy(begin, end, challenge.begin());
-      begin = end;
-      end = begin + data.size();
-      copy(begin, end, data.begin());
-    }
-  }
-  return result;
-}
-
-error_code DS28C36::computeAndReadPageAuthentication(int pageNum,
-                                                     AuthType authType) {
-  if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
-  }
-
-  const uint_least8_t parameter = (authType << 5) | pageNum;
-  return writeCommand(0xA5, make_span(&parameter, 1));
-}
-
-error_code
-DS28C36::computeAndReadPageAuthentication(int pageNum, KeyNum keyNum,
-                                          Signature::span 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);
-  }
-  error_code result = computeAndReadPageAuthentication(pageNum, authType);
-  if (!result) {
-    sleep(readMemoryTimeMs + generateEcdsaSignatureTimeMs);
-    uint_least8_t response[1 + 2 * Scalar::size];
-    result = readFixedLengthResponse(response);
-    if (!result) {
-      result = convertResultByte(response[0]);
-      const uint_least8_t * begin = response + 1;
-      const uint_least8_t * 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::computeAndReadPageAuthentication(int pageNum,
-                                                     SecretNum secretNum,
-                                                     Sha256::Hash::span 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);
-  }
-  error_code result = computeAndReadPageAuthentication(pageNum, authType);
-  if (!result) {
-    sleep(readMemoryTimeMs + sha256ComputationTimeMs);
-    array<uint_least8_t, 1 + Sha256::Hash::size> response;
-    result = readFixedLengthResponse(response);
-    if (!result) {
-      result = convertResultByte(response[0]);
-      copy(response.begin() + 1, response.end(), hmac.begin());
-    }
-  }
-  return result;
-}
-
-error_code DS28C36::authenticatedSha2WriteMemory(int pageNum,
-                                                 SecretNum secretNum,
-                                                 Page::const_span page) {
-  if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
-  }
-
-  uint_least8_t buffer[1 + Page::size];
-  buffer[0] = (secretNum << 6) | pageNum;
-  copy(page.begin(), page.end(), buffer + 1);
-  error_code result = writeCommand(0x99, buffer);
-  if (!result) {
-    sleep(writeMemoryTimeMs + (2 * sha256ComputationTimeMs));
-    result = readFixedLengthResponse(make_span(buffer, 1));
-    if (!result) {
-      result = convertResultByte(buffer[0]);
-    }
-  }
-  return result;
-}
-
-error_code DS28C36::computeAndLockSha2Secret(int pageNum, SecretNum msecretNum,
-                                             SecretNum dsecretNum,
-                                             bool writeProtectEnable) {
-  // User pages only
-  if (pageNum < 0 || pageNum > 15) {
-    return make_error_code(InvalidParameterError);
-  }
-
-  uint_least8_t buffer[] = {
-      static_cast<uint_least8_t>((dsecretNum << 6) | (msecretNum << 4) |
-                                 pageNum),
-      static_cast<uint_least8_t>(writeProtectEnable ? 0x80 : 0x00)};
-  error_code result = writeCommand(0x3C, buffer);
-  if (!result) {
-    sleep(sha256ComputationTimeMs +
-          ((writeProtectEnable ? 2 : 1) * writeMemoryTimeMs));
-    result = readFixedLengthResponse(make_span(buffer, 1));
-    if (!result) {
-      result = convertResultByte(buffer[0]);
-    }
-  }
-  return result;
-}
-
-error_code DS28C36::generateEcc256KeyPair(KeyNum keyNum,
-                                          bool writeProtectEnable) {
-  if (keyNum == KeyNumS) {
-    return make_error_code(InvalidParameterError);
-  }
-
-  uint_least8_t buffer = keyNum;
-  if (writeProtectEnable) {
-    buffer |= 0x80;
-  }
-  error_code result = writeCommand(0xCB, make_span(&buffer, 1));
-  if (!result) {
-    sleep(generateEccKeyPairTimeMs);
-    result = readFixedLengthResponse(make_span(&buffer, 1));
-    if (!result) {
-      result = convertResultByte(buffer);
-    }
-  }
-  return result;
-}
-
-error_code DS28C36::computeMultiblockHash(bool firstBlock, bool lastBlock,
-                                          span<const uint_least8_t> data) {
-  const span<const uint_least8_t>::index_type maxDataSize = 64;
-
-  if (data.size() < 1 || data.size() > maxDataSize) {
-    return make_error_code(InvalidParameterError);
-  }
-
-  uint_least8_t buffer[1 + maxDataSize];
-  buffer[0] = 0;
-  if (firstBlock) {
-    buffer[0] |= 0x40;
-  }
-  if (lastBlock) {
-    buffer[0] |= 0x80;
-  }
-  copy(data.begin(), data.end(), buffer + 1);
-  error_code result = writeCommand(0x33, make_span(buffer, data.size() + 1));
-  if (!result) {
-    sleep(sha256ComputationTimeMs);
-    result = readFixedLengthResponse(make_span(buffer, 1));
-    if (!result) {
-      result = convertResultByte(buffer[0]);
-    }
-  }
-  return result;
-}
-
-error_code DS28C36::verifyEcdsaSignature(KeyNum keyNum, HashType hashType,
-                                         Signature::const_span signature,
-                                         PioState pioa, PioState piob) {
-  uint_least8_t buffer[1 + 2 * Scalar::size];
-  buffer[0] = keyNum | (hashType << 2);
-  if (pioa != Unchanged) {
-    buffer[0] |= 0x20;
-  }
-  if (pioa == Conducting) {
-    buffer[0] |= 0x10;
-  }
-  if (piob != Unchanged) {
-    buffer[0] |= 0x80;
-  }
-  if (piob == Conducting) {
-    buffer[0] |= 0x40;
-  }
-  uint_least8_t * bufferIt =
-      copy(signature.r.begin(), signature.r.end(), buffer + 1);
-  copy(signature.s.begin(), signature.s.end(), bufferIt);
-  error_code result = writeCommand(0x59, buffer);
-  if (!result) {
-    sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs +
-          ((hashType == DataInBuffer) ? sha256ComputationTimeMs : 0));
-    result = readFixedLengthResponse(make_span(buffer, 1));
-    if (!result) {
-      result = convertResultByte(buffer[0]);
-    }
-  }
-  return result;
-}
-
-error_code
-DS28C36::authenticateEcdsaPublicKey(bool authWrites, bool ecdh, KeyNum keyNum,
-                                    int csOffset,
-                                    Signature::const_span signature) {
-  if (((keyNum != KeyNumA) && (keyNum != KeyNumB)) || (csOffset < 0) ||
-      (csOffset > 31)) {
-    return make_error_code(InvalidParameterError);
-  }
-
-  uint_least8_t buffer[1 + 2 * Scalar::size];
-  buffer[0] = (csOffset << 3) | (keyNum << 2);
-  if (ecdh) {
-    buffer[0] |= 0x02;
-  }
-  if (authWrites) {
-    buffer[0] |= 0x01;
-  }
-  uint_least8_t * bufferIt =
-      copy(signature.r.begin(), signature.r.end(), buffer + 1);
-  copy(signature.s.begin(), signature.s.end(), bufferIt);
-  error_code result = writeCommand(0xA8, buffer);
-  if (!result) {
-    sleep((ecdh ? 2 : 1) * verifyEsdsaSignatureOrComputeEcdhTimeMs);
-    result = readFixedLengthResponse(make_span(buffer, 1));
-    if (!result) {
-      result = convertResultByte(buffer[0]);
-    }
-  }
-  return result;
-}
-
-error_code DS28C36::authenticatedEcdsaWriteMemory(int pageNum,
-                                                  Page::const_span page) {
-  if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
-  }
-
-  uint_least8_t buffer[1 + Page::size];
-  buffer[0] = pageNum;
-  copy(page.begin(), page.end(), buffer + 1);
-  error_code result = writeCommand(0x89, buffer);
-  if (!result) {
-    sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs + writeMemoryTimeMs +
-          sha256ComputationTimeMs);
-    result = readFixedLengthResponse(make_span(buffer, 1));
-    if (!result) {
-      result = convertResultByte(buffer[0]);
-    }
-  }
-  return result;
-}
-
-error_code DS28C36::writeCommand(uint_least8_t command,
-                                 span<const uint_least8_t> parameters) {
-  error_code result = master->start(address_);
-  if (result) {
-    master->stop();
-    return result;
-  }
-  result = master->writeByte(command);
-  if (result) {
-    master->stop();
-    return result;
-  }
-  if (!parameters.empty()) {
-    result = master->writeByte(static_cast<uint_least8_t>(parameters.size()));
-    if (result) {
-      master->stop();
-      return result;
-    }
-    result = master->writeBlock(parameters);
-    if (result) {
-      master->stop();
-      return result;
-    }
-  }
-  result = master->stop();
-  return result;
-}
-
-error_code DS28C36::readVariableLengthResponse(span<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;
-  }
-  if (length > response.size()) {
-    master->stop();
-    return make_error_code(InvalidResponseError);
-  }
-  response = response.first(length);
-  if (!response.empty()) {
-    result = master->readBlock(I2CMaster::Nack, response);
-    if (result) {
-      master->stop();
-      return result;
-    }
-  }
-  result = master->stop();
-  return result;
-}
-
-error_code DS28C36::readFixedLengthResponse(span<uint_least8_t> response) {
-  const span<uint_least8_t>::index_type requestedResponseSize = response.size();
-  error_code result = readVariableLengthResponse(response);
-  if (!result && response.size() != requestedResponseSize) {
-    result = make_error_code(InvalidResponseError);
-  }
-  return result;
-}
-
-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 DS2476::generateEcdsaSignature(KeyNum keyNum,
-                                          Signature::span signature) {
-  if (keyNum == KeyNumS) {
-    return make_error_code(InvalidParameterError);
-  }
-
-  const uint_least8_t parameter = keyNum;
-  error_code result = writeCommand(0x1E, make_span(&parameter, 1));
-  if (!result) {
-    sleep(generateEcdsaSignatureTimeMs);
-    uint_least8_t response[1 + 2 * Scalar::size];
-    result = readFixedLengthResponse(response);
-    if (!result) {
-      result = convertResultByte(response[0]);
-      const uint_least8_t * begin = response + 1;
-      const uint_least8_t * 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 DS2476::computeSha2UniqueSecret(SecretNum msecretNum) {
-  uint_least8_t buffer = msecretNum << 4;
-  error_code result = writeCommand(0x55, make_span(&buffer, 1));
-  if (!result) {
-    sleep(sha256ComputationTimeMs);
-    result = readFixedLengthResponse(make_span(&buffer, 1));
-    if (!result) {
-      convertResultByte(buffer);
-    }
-  }
-  return result;
-}
-
-error_code DS2476::computeSha2Hmac(Sha256::Hash::span hmac) {
-  error_code result = writeCommand(0x2D);
-  if (!result) {
-    sleep(sha256ComputationTimeMs);
-    array<uint_least8_t, 1 + Sha256::Hash::size> response;
-    result = readFixedLengthResponse(response);
-    if (!result) {
-      result = convertResultByte(response[0]);
-      copy(response.begin() + 1, response.end(), hmac.begin());
-    }
-  }
-  return result;
-}
-
-error_code computeMultiblockHash(DS28C36 & ds28c36,
-                                 span<const uint_least8_t> data) {
-  error_code result;
-  span<const uint_least8_t>::index_type dataIdx = 0;
-  while (dataIdx < data.size() && !result) {
-    const span<const uint_least8_t>::index_type remainingSize =
-        data.size() - dataIdx;
-    const span<const uint_least8_t>::index_type chunkSize =
-        std::min<span<const uint_least8_t>::index_type>(remainingSize, 64);
-    result =
-        ds28c36.computeMultiblockHash(dataIdx == 0, remainingSize == chunkSize,
-                                      data.subspan(dataIdx, chunkSize));
-    dataIdx += chunkSize;
-  }
-  return result;
-}
-
-error_code verifyEcdsaSignature(DS28C36 & ds28c36, DS28C36::KeyNum publicKey,
-                                span<const uint_least8_t> data,
-                                Signature::const_span signature,
-                                DS28C36::PioState pioa,
-                                DS28C36::PioState piob) {
-  error_code result = computeMultiblockHash(ds28c36, data);
-  if (!result) {
-    result = ds28c36.verifyEcdsaSignature(publicKey, DS28C36::THASH, signature,
-                                          pioa, piob);
-  }
-  return result;
-}
-
-error_code verifyEcdsaSignature(DS28C36 & ds28c36,
-                                PublicKey::const_span publicKey,
-                                span<const uint_least8_t> data,
-                                Signature::const_span signature,
-                                DS28C36::PioState pioa,
-                                DS28C36::PioState piob) {
-  error_code result =
-      ds28c36.writeMemory(DS28C36::publicKeySxPage, publicKey.x);
-  if (!result) {
-    result = ds28c36.writeMemory(DS28C36::publicKeySyPage, publicKey.y);
-  }
-  if (!result) {
-    result = verifyEcdsaSignature(ds28c36, DS28C36::KeyNumS, data, signature,
-                                  pioa, piob);
-  }
-  return result;
-}
-
-error_code readRomIdAndManId(DS28C36 & ds28c36, RomId::span romId,
-                             ManId::span manId) {
-  DS28C36::Page::array page;
-  error_code result = ds28c36.readMemory(DS28C36::romOptionsPage, page);
-  if (!result) {
-    const DS28C36::RomOptions romOptions(page);
-    copy(romOptions.romId(), romId);
-    copy(romOptions.manId(), manId);
-  }
-  return result;
-}
-
-error_code enableCoprocessor(DS2476 & ds2476) {
-  DS2476::Page::array page;
-  error_code result = ds2476.readMemory(DS2476::gpioControlPage, page);
-  if (!result) {
-    DS2476::GpioControl gpioControl(page);
-    if (!gpioControl.pioaConducting()) {
-      gpioControl.setPioaConducting(true);
-      result = ds2476.writeMemory(DS2476::gpioControlPage, page);
-    }
-  }
-  return result;
-}
-
-error_code enableRomId(DS2476 & ds2476) {
-  DS2476::Page::array page;
-  error_code result = ds2476.readMemory(DS2476::romOptionsPage, page);
-  if (!result) {
-    DS2476::RomOptions romOptions(page);
-    if (!romOptions.romBlockDisable()) {
-      romOptions.setRomBlockDisable(true);
-      result = ds2476.writeMemory(DS2476::romOptionsPage, page);
-    }
-  }
-  return result;
-}
-
-static void setAnonymous(RomId::span romId) {
-  std::fill(romId.begin(), romId.end(), 0xFF);
-}
-
-DS28C36::PageAuthenticationData &
-DS28C36::PageAuthenticationData::setAnonymousRomId() {
-  setAnonymous(romId());
-  return *this;
-}
-
-DS28C36::EncryptionHmacData & DS28C36::EncryptionHmacData::setAnonymousRomId() {
-  setAnonymous(romId());
-  return *this;
-}
-
-} // namespace MaximInterface
--- a/Devices/DS28C36_DS2476.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,923 +0,0 @@
-/*******************************************************************************
-* 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 <stdint.h>
-#include <vector>
-#include <MaximInterface/Links/I2CMaster.hpp>
-#include <MaximInterface/Links/Sleep.hpp>
-#include <MaximInterface/Utilities/array_span.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.
-  };
-
-  /// @name Device memory pages
-  /// @{
-  
-  static const int publicKeyAxPage = 16;
-  static const int publicKeyAyPage = 17;
-  static const int publicKeyBxPage = 18;
-  static const int publicKeyByPage = 19;
-  static const int publicKeyCxPage = 20;
-  static const int publicKeyCyPage = 21;
-  static const int privateKeyAPage = 22;
-  static const int privateKeyBPage = 23;
-  static const int privateKeyCPage = 24;
-  static const int secretAPage = 25;
-  static const int secretBPage = 26;
-  static const int decrementCounterPage = 27;
-  static const int romOptionsPage = 28;
-  static const int gpioControlPage = 29;
-  static const int publicKeySxPage = 30;
-  static const int publicKeySyPage = 31;
-  
-  /// @}
-
-  /// Number of memory pages on the device.
-  static const int memoryPages = 32;
-
-  /// 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_span<uint_least8_t, 32> Page;
-
-  // Format page authentication input data.
-  class PageAuthenticationData;
-
-  // Format authenticated write input data.
-  class WriteAuthenticationData;
-
-  // Format compute secret input data.
-  class ComputeSecretData;
-
-  // Format encryption or decryption HMAC input data.
-  class EncryptionHmacData;
-
-  // Access fields in the ROM Options page.
-  class RomOptions;
-
-  // Access fields in the GPIO Control page.
-  class GpioControl;
-
-  /// 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;
-
-  /// Challenge for an encrypted device memory page.
-  typedef array_span<uint_least8_t, 8> EncryptionChallenge;
-
-  DS28C36(Sleep & sleep, I2CMaster & master, uint_least8_t address = 0x36)
-      : sleep_(&sleep), master(&master), address_(address & 0xFE) {}
-
-  void setSleep(Sleep & sleep) { sleep_ = &sleep; }
-
-  void setMaster(I2CMaster & master) { this->master = &master; }
-
-  uint_least8_t address() const { return address_; }
-
-  void setAddress(uint_least8_t address) { address_ = address & 0xFE; }
-
-  /// @brief Write memory with no protection.
-  /// @param pageNum Number of page to write.
-  /// @param page Data to write.
-  MaximInterface_EXPORT error_code writeMemory(int pageNum,
-                                               Page::const_span page);
-
-  /// @brief 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::span page);
-
-  /// @brief Write the temporary buffer.
-  /// @param data Data to write.
-  MaximInterface_EXPORT error_code writeBuffer(span<const uint_least8_t> data);
-
-  /// @brief Read the temporary buffer.
-  /// @param[out] data Data that was read.
-  MaximInterface_EXPORT error_code
-  readBuffer(std::vector<uint_least8_t> & data);
-
-  /// @brief 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);
-
-  /// @brief 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();
-
-  /// @brief Read a block of random data from the RNG.
-  /// @param[out] data Random data from RNG with length from 1 to 64.
-  MaximInterface_EXPORT error_code readRng(span<uint_least8_t> data);
-
-  /// @brief Read memory with encryption.
-  /// @param pageNum Number of page to read from.
-  /// @param secretNum Secret to use for encryption.
-  /// @param[out] challenge Encryption challenge that was read.
-  /// @param[out] data Encrypted page data that was read.
-  MaximInterface_EXPORT error_code
-  encryptedReadMemory(int pageNum, SecretNum secretNum,
-                      EncryptionChallenge::span challenge, Page::span data);
-
-  /// @brief 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 computeAndReadPageAuthentication(
-      int pageNum, KeyNum keyNum, Ecc256::Signature::span signature);
-
-  /// @brief 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 computeAndReadPageAuthentication(
-      int pageNum, SecretNum secretNum, Sha256::Hash::span hmac);
-
-  /// @brief 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, Page::const_span page);
-
-  /// @brief 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);
-
-  /// @brief 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);
-
-  /// @brief 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. Should be 64 bytes unless this is the last block.
-  MaximInterface_EXPORT error_code computeMultiblockHash(
-      bool firstBlock, bool lastBlock, span<const uint_least8_t> data);
-
-  /// @brief 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, Ecc256::Signature::const_span signature,
-      PioState pioa = Unchanged, PioState piob = Unchanged);
-
-  /// @brief
-  /// 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,
-      Ecc256::Signature::const_span signature);
-
-  /// @brief Write with ECDSA authentication.
-  /// @param pageNum Number of page to write.
-  /// @param page Data to write.
-  MaximInterface_EXPORT error_code
-  authenticatedEcdsaWriteMemory(int pageNum, Page::const_span page);
-
-  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,
-                          span<const uint_least8_t> parameters);
-
-  error_code writeCommand(uint_least8_t command) {
-    return writeCommand(command, span<const uint_least8_t>());
-  }
-
-  error_code readVariableLengthResponse(span<uint_least8_t> & response);
-
-  error_code readFixedLengthResponse(span<uint_least8_t> response);
-
-  void sleep(int ms) const { sleep_->invoke(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_;
-
-  error_code computeAndReadPageAuthentication(int pageNum, AuthType authType);
-};
-
-/// Interface to the DS2476 coprocessor.
-class DS2476 : public DS28C36 {
-public:
-  DS2476(Sleep & sleep, I2CMaster & master, uint_least8_t address = 0x76)
-      : DS28C36(sleep, master, address) {}
-
-  /// @brief 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::span signature);
-
-  /// @brief Compute unique SHA2 secret.
-  /// @param msecretNum Master secret to use in computation.
-  MaximInterface_EXPORT error_code
-  computeSha2UniqueSecret(SecretNum msecretNum);
-
-  /// @brief Compute SHA2 HMAC.
-  /// @param[out] hmac Computed HMAC.
-  MaximInterface_EXPORT error_code computeSha2Hmac(Sha256::Hash::span hmac);
-};
-
-inline error_code make_error_code(DS28C36::ErrorValue e) {
-  return error_code(e, DS28C36::errorCategory());
-}
-
-/// @brief
-/// Hash arbitrary length data with successive Compute Multiblock Hash commands.
-/// @param ds28c36 Device for computation.
-/// @param data Data to hash.
-MaximInterface_EXPORT error_code
-computeMultiblockHash(DS28C36 & ds28c36, span<const uint_least8_t> data);
-
-/// @brief Verify ECDSA signature.
-/// @param ds28c36 Device for computation.
-/// @param publicKey Public key to use for verification.
-/// @param data 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,
-    span<const uint_least8_t> data, Ecc256::Signature::const_span signature,
-    DS28C36::PioState pioa = DS28C36::Unchanged,
-    DS28C36::PioState piob = DS28C36::Unchanged);
-
-/// @brief Verify ECDSA signature.
-/// @param ds28c36 Device for computation.
-/// @param publicKey
-/// Public key to use for verification which is loaded into Public Key S.
-/// @param data 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, Ecc256::PublicKey::const_span publicKey,
-    span<const uint_least8_t> data, Ecc256::Signature::const_span signature,
-    DS28C36::PioState pioa = DS28C36::Unchanged,
-    DS28C36::PioState piob = DS28C36::Unchanged);
-
-/// @brief
-/// Read the device ROM ID and MAN ID using the Read Memory command on the
-/// ROM Options page.
-/// @param ds28c36 Device to read.
-/// @param[out] romId Read ROM ID valid when operation is successful.
-/// @param[out] manId Read MAN ID valid when operation is successful.
-MaximInterface_EXPORT error_code readRomIdAndManId(DS28C36 & ds28c36,
-                                                   RomId::span romId,
-                                                   ManId::span manId);
-
-/// @brief
-/// Enable coprocessor functionality on the DS2476 by writing to the
-/// GPIO Control page.
-MaximInterface_EXPORT error_code enableCoprocessor(DS2476 & ds2476);
-
-/// @brief
-/// Disable blocking of the ROM ID on the DS2476 by writing to the
-/// ROM Options page.
-MaximInterface_EXPORT error_code enableRomId(DS2476 & ds2476);
-
-/// Format page authentication input data.
-class DS28C36::PageAuthenticationData {
-public:
-  typedef array_span<uint_least8_t,
-                     RomId::size + 2 * Page::size + 1 + ManId::size>
-      Result;
-
-  PageAuthenticationData() : result_() {}
-
-  /// Formatted data result.
-  Result::const_span result() const { return result_; }
-
-  /// @name ROM ID
-  /// @brief 1-Wire ROM ID of the device.
-  /// @{
-  
-  /// Get mutable ROM ID.
-  RomId::span romId() {
-    return make_span(result_).subspan<romIdIdx, RomId::size>();
-  }
-
-  /// Get immutable ROM ID.
-  RomId::const_span romId() const {
-    return const_cast<PageAuthenticationData &>(*this).romId();
-  }
-
-  /// Set ROM ID.
-  PageAuthenticationData & setRomId(RomId::const_span romId) {
-    copy(romId, this->romId());
-    return *this;
-  }
-
-  /// Set ROM ID for use in anonymous mode.
-  MaximInterface_EXPORT PageAuthenticationData & setAnonymousRomId();
-  
-  /// @}
-
-  /// @name Page
-  /// @brief Data from a device memory page.
-  /// @{
-
-  /// Get mutable page.
-  Page::span page() {
-    return make_span(result_).subspan<pageIdx, Page::size>();
-  }
-
-  /// Get immutable page.
-  Page::const_span page() const {
-    return const_cast<PageAuthenticationData &>(*this).page();
-  }
-
-  /// Set page.
-  PageAuthenticationData & setPage(Page::const_span page) {
-    copy(page, this->page());
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name Challenge
-  /// @brief Random challenge used to prevent replay attacks.
-  /// @{
-  
-  /// Get mutable Challenge.
-  Page::span challenge() {
-    return make_span(result_).subspan<challengeIdx, Page::size>();
-  }
-
-  /// Get immutable Challenge.
-  Page::const_span challenge() const {
-    return const_cast<PageAuthenticationData &>(*this).challenge();
-  }
-
-  /// Set Challenge.
-  PageAuthenticationData & setChallenge(Page::const_span challenge) {
-    copy(challenge, this->challenge());
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name Page number
-  /// @brief Number of the page to use data from.
-  /// @{
-  
-  /// Get page number.
-  int pageNum() const { return result_[pageNumIdx]; }
-
-  /// Set page number.
-  PageAuthenticationData & setPageNum(int pageNum) {
-    result_[pageNumIdx] = pageNum;
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name MAN ID
-  /// @brief Manufacturer ID of the device.
-  /// @{
-  
-  /// Get mutable MAN ID.
-  ManId::span manId() {
-    return make_span(result_).subspan<manIdIdx, ManId::size>();
-  }
-
-  /// Get immutable MAN ID.
-  ManId::const_span manId() const {
-    return const_cast<PageAuthenticationData &>(*this).manId();
-  }
-
-  /// Set MAN ID.
-  PageAuthenticationData & setManId(ManId::const_span manId) {
-    copy(manId, this->manId());
-    return *this;
-  }
-  
-  /// @}
-
-private:
-  typedef Result::span::index_type index;
-
-  static const index romIdIdx = 0;
-  static const index pageIdx = romIdIdx + RomId::size;
-  static const index challengeIdx = pageIdx + Page::size;
-  static const index pageNumIdx = challengeIdx + Page::size;
-  static const index manIdIdx = pageNumIdx + 1;
-
-  Result::array result_;
-};
-
-/// Format authenticated write input data.
-class DS28C36::WriteAuthenticationData {
-public:
-  typedef PageAuthenticationData::Result Result;
-
-  WriteAuthenticationData() : data() {}
-
-  /// Formatted data result.
-  Result::const_span result() const { return data.result(); }
-
-  /// @name ROM ID
-  /// @brief 1-Wire ROM ID of the device.
-  /// @{
-  
-  /// Get mutable ROM ID.
-  RomId::span romId() { return data.romId(); }
-
-  /// Get immutable ROM ID.
-  RomId::const_span romId() const { return data.romId(); }
-
-  /// Set ROM ID.
-  WriteAuthenticationData & setRomId(RomId::const_span romId) {
-    data.setRomId(romId);
-    return *this;
-  }
-
-  /// Set ROM ID for use in anonymous mode.
-  WriteAuthenticationData & setAnonymousRomId() {
-    data.setAnonymousRomId();
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name Old page
-  /// @brief Existing data contained in the page.
-  /// @{
-  
-  /// Get mutable old page.
-  Page::span oldPage() { return data.page(); }
-
-  /// Get immutable old page.
-  Page::const_span oldPage() const { return data.page(); }
-
-  /// Set old page.
-  WriteAuthenticationData & setOldPage(Page::const_span oldPage) {
-    data.setPage(oldPage);
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name New page
-  /// @brief New data to write to the page.
-  /// @{
-  
-  /// Get mutable new page.
-  Page::span newPage() { return data.challenge(); }
-
-  /// Get immutable new page.
-  Page::const_span newPage() const { return data.challenge(); }
-
-  /// Set new page.
-  WriteAuthenticationData & setNewPage(Page::const_span newPage) {
-    data.setChallenge(newPage);
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name Page number
-  /// @brief Page number for write operation.
-  /// @{
-
-  /// Get page number.
-  int pageNum() const { return data.pageNum(); }
-
-  /// Set page number.
-  WriteAuthenticationData & setPageNum(int pageNum) {
-    data.setPageNum(pageNum);
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name MAN ID
-  /// @brief Manufacturer ID of the device.
-  /// @{
-
-  /// Get mutable MAN ID.
-  ManId::span manId() { return data.manId(); }
-
-  /// Get immutable MAN ID.
-  ManId::const_span manId() const { return data.manId(); }
-
-  /// Set MAN ID.
-  WriteAuthenticationData & setManId(ManId::const_span manId) {
-    data.setManId(manId);
-    return *this;
-  }
-  
-  /// @}
-
-private:
-  PageAuthenticationData data;
-};
-
-/// Format compute secret input data.
-class DS28C36::ComputeSecretData {
-public:
-  typedef PageAuthenticationData::Result Result;
-
-  ComputeSecretData() : data() {}
-
-  /// Formatted data result.
-  Result::const_span result() const { return data.result(); }
-
-  /// @name ROM ID
-  /// @brief 1-Wire ROM ID of the device.
-  /// @{
-  
-  /// Get mutable ROM ID.
-  RomId::span romId() { return data.romId(); }
-
-  /// Get immutable ROM ID.
-  RomId::const_span romId() const { return data.romId(); }
-
-  /// Set ROM ID.
-  ComputeSecretData & setRomId(RomId::const_span romId) {
-    data.setRomId(romId);
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name Binding Data
-  /// @brief Binding Data contained in the selected page.
-  /// @{
-  
-  /// Get mutable Binding Data.
-  Page::span bindingData() { return data.page(); }
-
-  /// Get immutable Binding Data.
-  Page::const_span bindingData() const { return data.page(); }
-
-  /// Set Binding Data.
-  ComputeSecretData & setBindingData(Page::const_span bindingData) {
-    data.setPage(bindingData);
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name Partial Secret
-  /// @brief Partial Secret used for customization.
-  /// @{
-  
-  /// Get mutable Partial Secret.
-  Page::span partialSecret() { return data.challenge(); }
-
-  /// Get immutable Partial Secret.
-  Page::const_span partialSecret() const { return data.challenge(); }
-
-  /// Set Partial Secret.
-  ComputeSecretData & setPartialSecret(Page::const_span partialSecret) {
-    data.setChallenge(partialSecret);
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name Page number
-  /// @brief Page number for Binding Data.
-  /// @{
-  
-  /// Get page number.
-  int pageNum() const { return data.pageNum(); }
-
-  /// Set page number.
-  ComputeSecretData & setPageNum(int pageNum) {
-    data.setPageNum(pageNum);
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name MAN ID
-  /// @brief Manufacturer ID of the device.
-  /// @{
-  
-  /// Get mutable MAN ID.
-  ManId::span manId() { return data.manId(); }
-
-  /// Get immutable MAN ID.
-  ManId::const_span manId() const { return data.manId(); }
-
-  /// Set MAN ID.
-  ComputeSecretData & setManId(ManId::const_span manId) {
-    data.setManId(manId);
-    return *this;
-  }
-  
-  /// @}
-
-private:
-  PageAuthenticationData data;
-};
-
-/// Format encryption or decryption HMAC input data.
-class DS28C36::EncryptionHmacData {
-public:
-  typedef array_span<uint_least8_t,
-                     EncryptionChallenge::size + RomId::size + 1 + ManId::size>
-      Result;
-
-  EncryptionHmacData() : result_() {}
-
-  /// Formatted data result.
-  Result::const_span result() const { return result_; }
-
-  /// @name Encryption Challenge
-  /// @brief Random challenge used to prevent replay attacks.
-  /// @{
-  
-  /// Get mutable Encryption Challenge.
-  EncryptionChallenge::span encryptionChallenge() {
-    return make_span(result_)
-        .subspan<encryptionChallengeIdx, EncryptionChallenge::size>();
-  }
-
-  /// Get immutable Encryption Challenge.
-  EncryptionChallenge::const_span encryptionChallenge() const {
-    return const_cast<EncryptionHmacData &>(*this).encryptionChallenge();
-  }
-
-  /// Set Encryption Challenge.
-  EncryptionHmacData &
-  setEncryptionChallenge(EncryptionChallenge::const_span encryptionChallenge) {
-    copy(encryptionChallenge, this->encryptionChallenge());
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name ROM ID
-  /// @brief 1-Wire ROM ID of the device.
-  /// @{
-  
-  /// Get mutable ROM ID.
-  RomId::span romId() {
-    return make_span(result_).subspan<romIdIdx, RomId::size>();
-  }
-
-  /// Get immutable ROM ID.
-  RomId::const_span romId() const {
-    return const_cast<EncryptionHmacData &>(*this).romId();
-  }
-
-  /// Set ROM ID.
-  EncryptionHmacData & setRomId(RomId::const_span romId) {
-    copy(romId, this->romId());
-    return *this;
-  }
-
-  /// Set ROM ID for use in anonymous mode.
-  MaximInterface_EXPORT EncryptionHmacData & setAnonymousRomId();
-  
-  /// @}
-
-  /// @name Page number
-  /// @brief Number of the page to use data from.
-  /// @{
-  
-  /// Get page number.
-  int pageNum() const { return result_[pageNumIdx]; }
-
-  /// Set page number.
-  EncryptionHmacData & setPageNum(int pageNum) {
-    result_[pageNumIdx] = pageNum;
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name MAN ID
-  /// @brief Manufacturer ID of the device.
-  /// @{
-
-  /// Get mutable MAN ID.
-  ManId::span manId() {
-    return make_span(result_).subspan<manIdIdx, ManId::size>();
-  }
-
-  /// Get immutable MAN ID.
-  ManId::const_span manId() const {
-    return const_cast<EncryptionHmacData &>(*this).manId();
-  }
-
-  /// Set MAN ID.
-  EncryptionHmacData & setManId(ManId::const_span manId) {
-    copy(manId, this->manId());
-    return *this;
-  }
-  
-  /// @}
-
-private:
-  typedef Result::span::index_type index;
-
-  static const index encryptionChallengeIdx = 0;
-  static const index romIdIdx =
-      encryptionChallengeIdx + EncryptionChallenge::size;
-  static const index pageNumIdx = romIdIdx + RomId::size;
-  static const index manIdIdx = pageNumIdx + 1;
-
-  Result::array result_;
-};
-
-/// Access fields in the ROM Options page.
-class DS28C36::RomOptions {
-public:
-  explicit RomOptions(Page::span page) : page(page) {}
-
-  bool romBlockDisable() const {
-    return page[romBlockDisableIdx] == enabledValue;
-  }
-  
-  RomOptions & setRomBlockDisable(bool romBlockDisable) {
-    page[romBlockDisableIdx] = (romBlockDisable ? enabledValue : 0);
-    return *this;
-  }
-  
-  bool anonymous() const { return page[anonymousIdx] == enabledValue; }
-
-  RomOptions & setAnonymous(bool anonymous) {
-    page[anonymousIdx] = (anonymous ? enabledValue : 0);
-    return *this;
-  }
-
-  ManId::const_span manId() const {
-    return page.subspan<22, ManId::size>();
-  }
-
-  RomId::const_span romId() const {
-    return page.subspan<24, RomId::size>();
-  }
-
-private:
-  static const Page::span::index_type romBlockDisableIdx = 0;
-  static const Page::span::index_type anonymousIdx = 1;
-  static const Page::span::value_type enabledValue = 0xAA;
-
-  Page::span page;
-};
-
-/// Access fields in the GPIO Control page.
-class DS28C36::GpioControl {
-public:
-  explicit GpioControl(Page::span page) : page(page) {}
-
-  bool pioaConducting() const {
-    return page[pioaConductingIdx] == pioConductingValue;
-  }
-
-  GpioControl & setPioaConducting(bool pioaConducting) {
-    page[pioaConductingIdx] = (pioaConducting ? pioConductingValue : 0x55);
-    return *this;
-  }
-
-  bool piobConducting() const {
-    return page[piobConductingIdx] == pioConductingValue;
-  }
-
-  GpioControl & setPiobConducting(bool piobConducting) {
-    page[piobConductingIdx] = (piobConducting ? pioConductingValue : 0x55);
-    return *this;
-  }
-
-  bool pioaLevel() const { return page[2] == pioLevelValue; }
-
-  bool piobLevel() const { return page[3] == pioLevelValue; }
-
-private:
-  static const Page::span::index_type pioaConductingIdx = 0;
-  static const Page::span::index_type piobConductingIdx = 1;
-  static const Page::span::value_type pioConductingValue = 0xAA;
-  static const Page::span::value_type pioLevelValue = 0x55;
-
-  Page::span page;
-};
-
-} // namespace MaximInterface
-
-#endif
--- a/Devices/DS28E15_22_25.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,653 +0,0 @@
-/*******************************************************************************
-* 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/Utilities/crc.hpp>
-#include <MaximInterface/Utilities/Error.hpp>
-#include "DS28E15_22_25.hpp"
-
-namespace MaximInterface {
-
-using namespace Sha256;
-using std::copy;
-
-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, span<const uint_least8_t> data,
-                 OneWireMaster::Level level = OneWireMaster::NormalLevel,
-                 uint_fast16_t crcStart = 0) {
-  error_code result = master.writeBlock(data);
-  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, calculateCrc16(data, crcStart)) != 0xB001) {
-    result = make_error_code(DS28E15_22_25::CrcError);
-  }
-  return result;
-}
-
-const int DS28E15_22_25::segmentsPerPage;
-
-DS28E15_22_25::AuthenticationData &
-DS28E15_22_25::AuthenticationData::setAnonymousRomId() {
-  std::fill(romId().begin(), romId().end(), 0xFF);
-  return *this;
-}
-
-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);
-  }
-  return result;
-}
-
-static error_code readDataWithCrc(OneWireMaster & master,
-                                  span<uint_least8_t> data) {
-  error_code result = master.readBlock(data);
-  if (result) {
-    return result;
-  }
-  uint_least8_t response[2];
-  result = master.readBlock(response);
-  if (result) {
-    return result;
-  }
-  if (calculateCrc16(response, calculateCrc16(data)) != 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, 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 &
-DS28E15_22_25::BlockProtection::setBlockNum(int blockNum) {
-  status &= ~blockNumMask;
-  status |= (blockNum & blockNumMask);
-  return *this;
-}
-
-bool DS28E15_22_25::BlockProtection::noProtection() const {
-  return !readProtection() && !writeProtection() && !eepromEmulation() &&
-         !authProtection();
-}
-
-DS28E15_22_25::BlockProtection &
-DS28E15_22_25::BlockProtection::setReadProtection(bool readProtection) {
-  if (readProtection) {
-    status |= readProtectionMask;
-  } else {
-    status &= ~readProtectionMask;
-  }
-  return *this;
-}
-
-DS28E15_22_25::BlockProtection &
-DS28E15_22_25::BlockProtection::setWriteProtection(bool writeProtection) {
-  if (writeProtection) {
-    status |= writeProtectionMask;
-  } else {
-    status &= ~writeProtectionMask;
-  }
-  return *this;
-}
-
-DS28E15_22_25::BlockProtection &
-DS28E15_22_25::BlockProtection::setEepromEmulation(bool eepromEmulation) {
-  if (eepromEmulation) {
-    status |= eepromEmulationMask;
-  } else {
-    status &= ~eepromEmulationMask;
-  }
-  return *this;
-}
-
-DS28E15_22_25::BlockProtection &
-DS28E15_22_25::BlockProtection::setAuthProtection(bool authProtection) {
-  if (authProtection) {
-    status |= authProtectionMask;
-  } else {
-    status &= ~authProtectionMask;
-  }
-  return *this;
-}
-
-DS28E15_22_25::ProtectionWriteMacData::ProtectionWriteMacData()
-    : result_(), oldProtection_(), newProtection_() {
-  setOldProtection(oldProtection_);
-  setNewProtection(newProtection_);
-}
-
-DS28E15_22_25::ProtectionWriteMacData &
-DS28E15_22_25::ProtectionWriteMacData::setOldProtection(
-    BlockProtection oldProtection) {
-  result_[oldProtectionIdx] = oldProtection.authProtection() ? 1 : 0;
-  result_[oldProtectionIdx + 1] = oldProtection.eepromEmulation() ? 1 : 0;
-  result_[oldProtectionIdx + 2] = oldProtection.writeProtection() ? 1 : 0;
-  result_[oldProtectionIdx + 3] = oldProtection.readProtection() ? 1 : 0;
-  oldProtection_ = oldProtection;
-  return *this;
-}
-
-DS28E15_22_25::ProtectionWriteMacData &
-DS28E15_22_25::ProtectionWriteMacData::setNewProtection(
-    BlockProtection newProtection) {
-  result_[blockNumIdx] = newProtection.blockNum();
-  result_[newProtectionIdx] = newProtection.authProtection() ? 1 : 0;
-  result_[newProtectionIdx + 1] = newProtection.eepromEmulation() ? 1 : 0;
-  result_[newProtectionIdx + 2] = newProtection.writeProtection() ? 1 : 0;
-  result_[newProtectionIdx + 3] = newProtection.readProtection() ? 1 : 0;
-  newProtection_ = newProtection;
-  return *this;
-}
-
-error_code
-DS28E15_22_25::writeAuthBlockProtection(BlockProtection newProtection,
-                                        Hash::const_span mac) {
-  error_code result =
-      writeCommandWithCrc(AuthWriteBlockProtection, newProtection.statusByte(),
-                          OneWireMaster::StrongLevel);
-  if (result) {
-    return result;
-  }
-
-  sleep->invoke(shaComputationDelayMs);
-  result = master->setLevel(OneWireMaster::NormalLevel);
-  if (result) {
-    return result;
-  }
-
-  result = writeDataWithCrc(*master, mac);
-  if (result) {
-    return result;
-  }
-
-  result = readCsByte(*master);
-  if (result) {
-    return result;
-  }
-
-  result = releaseSequence(*master, *sleep, eepromWriteDelayMs);
-  return result;
-}
-
-error_code DS28E15_22_25::writeBlockProtection(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;
-}
-
-error_code DS28E15_22_25::computeReadPageMac(int page_num, bool anon,
-                                             Hash::span mac) const {
-  error_code result =
-      writeCommandWithCrc(ComputePageMac, (anon ? 0xE0 : 0x00) | page_num,
-                          OneWireMaster::StrongLevel);
-  if (result) {
-    return result;
-  }
-
-  sleep->invoke(shaComputationDelayMs * 2);
-  result = master->setLevel(OneWireMaster::NormalLevel);
-  if (result) {
-    return result;
-  }
-
-  result = readCsByte(*master);
-  if (result) {
-    return result;
-  }
-
-  result = readDataWithCrc(*master, mac);
-  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(Scratchpad::const_span 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);
-  return result;
-}
-
-error_code DS28E15_22_25::doReadScratchpad(Scratchpad::span 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);
-  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::span rdbuf) const {
-  error_code result = writeCommandWithCrc(ReadMemory, page);
-  if (result) {
-    return result;
-  }
-
-  result = continueReadPage(rdbuf);
-  return result;
-}
-
-error_code DS28E15_22_25::continueReadPage(Page::span rdbuf) const {
-  return readDataWithCrc(*master, rdbuf);
-}
-
-error_code DS28E15_22_25::doWriteAuthSegment(Segment::const_span newData,
-                                             Hash::const_span 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, OneWireMaster::StrongLevel, crcStart);
-  if (result) {
-    return result;
-  }
-
-  sleep->invoke(shaComputationDelayMs);
-  result = master->setLevel(OneWireMaster::NormalLevel);
-  if (result) {
-    return result;
-  }
-
-  result = writeDataWithCrc(*master, mac);
-  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,
-                                             Segment::const_span newData,
-                                             Hash::const_span 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(
-    Segment::const_span newData, Hash::const_span mac, Variant variant) {
-  return doWriteAuthSegment(newData, mac, variant, true);
-}
-
-error_code DS28E15_22_25::readSegment(int page, int segment,
-                                      Segment::span 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::span data) const {
-  return master->readBlock(data);
-}
-
-error_code DS28E15_22_25::writeSegment(int page, int block,
-                                       Segment::const_span data) {
-  error_code result = writeCommandWithCrc(WriteMemory, (block << 5) | page);
-  if (result) {
-    return result;
-  }
-
-  result = continueWriteSegment(data);
-  return result;
-}
-
-error_code DS28E15_22_25::continueWriteSegment(Segment::const_span data) {
-  error_code result = writeDataWithCrc(*master, data);
-  if (result) {
-    return result;
-  }
-
-  result = releaseSequence(*master, *sleep, eepromWriteDelayMs);
-  return result;
-}
-
-error_code
-DS28E15_22_25::doReadAllBlockProtection(span<BlockProtection> protection,
-                                        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);
-      if (!result) {
-        const int blocks = ((variant == DS28E22) ? DS28E22::memoryPages
-                                                 : DS28E25::memoryPages) /
-                           ds28e22_25_pagesPerBlock;
-        for (span<BlockProtection>::index_type i = 0;
-             i < std::min<span<BlockProtection>::index_type>(protection.size(),
-                                                             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);
-      if (!result) {
-        for (span<BlockProtection>::index_type i = 0;
-             i < std::min<span<BlockProtection>::index_type>(
-                     protection.size(), 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) {
-    uint_least8_t data[4];
-    result = readDataWithCrc(*master, data);
-    if (!result) {
-      personality.PB1 = data[0];
-      personality.PB2 = data[1];
-      personality.manId[0] = data[2];
-      personality.manId[1] = data[3];
-    }
-  }
-  return result;
-}
-
-const int DS28EL15::memoryPages;
-const int DS28EL15::protectionBlocks;
-
-error_code DS28EL15::writeScratchpad(Scratchpad::const_span data) {
-  return doWriteScratchpad(data, DS28E15);
-}
-
-error_code DS28EL15::readScratchpad(Scratchpad::span 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,
-                                      Segment::const_span newData,
-                                      Hash::const_span mac) {
-  return doWriteAuthSegment(pageNum, segmentNum, newData, mac, DS28E15);
-}
-
-error_code DS28EL15::continueWriteAuthSegment(Segment::const_span newData,
-                                              Hash::const_span mac) {
-  return doContinueWriteAuthSegment(newData, mac, DS28E15);
-}
-
-error_code DS28EL15::readAllBlockProtection(
-    span<BlockProtection, protectionBlocks> protection) const {
-  return doReadAllBlockProtection(protection, DS28E15);
-}
-
-error_code DS28E15::loadSecret(bool lock) { return doLoadSecret(lock, false); }
-
-error_code DS28E15::computeSecret(int pageNum, bool lock) {
-  return doComputeSecret(pageNum, lock, false);
-}
-
-const int DS28EL22::memoryPages;
-const int DS28EL22::protectionBlocks;
-
-error_code DS28EL22::writeScratchpad(Scratchpad::const_span data) {
-  return doWriteScratchpad(data, DS28E22);
-}
-
-error_code DS28EL22::readScratchpad(Scratchpad::span 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,
-                                      Segment::const_span newData,
-                                      Hash::const_span mac) {
-  return doWriteAuthSegment(pageNum, segmentNum, newData, mac, DS28E22);
-}
-
-error_code DS28EL22::continueWriteAuthSegment(Segment::const_span newData,
-                                              Hash::const_span mac) {
-  return doContinueWriteAuthSegment(newData, mac, DS28E22);
-}
-
-error_code DS28EL22::readAllBlockProtection(
-    span<BlockProtection, protectionBlocks> protection) const {
-  return doReadAllBlockProtection(protection, DS28E22);
-}
-
-error_code DS28E22::loadSecret(bool lock) { return doLoadSecret(lock, false); }
-
-error_code DS28E22::computeSecret(int pageNum, bool lock) {
-  return doComputeSecret(pageNum, lock, false);
-}
-
-const int DS28EL25::memoryPages;
-const int DS28EL25::protectionBlocks;
-
-error_code DS28EL25::writeScratchpad(Scratchpad::const_span data) {
-  return doWriteScratchpad(data, DS28E25);
-}
-
-error_code DS28EL25::readScratchpad(Scratchpad::span 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,
-                                      Segment::const_span newData,
-                                      Hash::const_span mac) {
-  return doWriteAuthSegment(pageNum, segmentNum, newData, mac, DS28E25);
-}
-
-error_code DS28EL25::continueWriteAuthSegment(Segment::const_span newData,
-                                              Hash::const_span mac) {
-  return doContinueWriteAuthSegment(newData, mac, DS28E25);
-}
-
-error_code DS28EL25::readAllBlockProtection(
-    span<BlockProtection, protectionBlocks> protection) const {
-  return doReadAllBlockProtection(protection, 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
--- a/Devices/DS28E15_22_25.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,885 +0,0 @@
-/*******************************************************************************
-* 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 <stdint.h>
-#include <MaximInterface/Links/OneWireMaster.hpp>
-#include <MaximInterface/Links/SelectRom.hpp>
-#include <MaximInterface/Links/Sleep.hpp>
-#include <MaximInterface/Utilities/array_span.hpp>
-#include <MaximInterface/Utilities/Export.h>
-#include <MaximInterface/Utilities/ManId.hpp>
-#include <MaximInterface/Utilities/Sha256.hpp>
-
-namespace MaximInterface {
-
-/// @brief
-/// 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_span<uint_least8_t, 4> Segment;
-
-  /// Holds the contents of a device memory page.
-  typedef array_span<uint_least8_t, 32> Page;
-
-  /// Number of segments per page.
-  static const int segmentsPerPage = Page::size / Segment::size;
-
-  /// Holds the contents of the device scratchpad.
-  typedef array_span<uint_least8_t, 32> Scratchpad;
-
-  /// Container for the device personality.
-  struct Personality {
-    uint_least8_t PB1;
-    uint_least8_t PB2;
-    ManId::array manId;
-
-    bool secretLocked() const { return PB2 & 0x01; }
-  };
-
-  // Represents the status of a memory protection block.
-  class BlockProtection;
-
-  // Format data to hash for an Authenticated Write to a memory segment.
-  class SegmentWriteMacData;
-
-  // Format data to hash for an Authenticated Write to a memory protection block.
-  class ProtectionWriteMacData;
-
-  // Format data to hash for device authentication or computing the next secret
-  // from the existing secret.
-  class AuthenticationData;
-
-  void setSleep(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.
-
-  /// @brief 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::span data) const;
-
-  /// @brief 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::span data) const;
-
-  /// @brief 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,
-                                                Segment::const_span data);
-
-  /// @brief Continue an in-progress Write Memory command.
-  /// @param[in] data Data to write to the memory segment.
-  MaximInterface_EXPORT error_code
-  continueWriteSegment(Segment::const_span data);
-
-  /// @brief 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::span rdbuf) const;
-
-  /// @brief Continue an in-progress readPageOperation.
-  /// @param[out] rdbuf Buffer to read data from the page into.
-  MaximInterface_EXPORT error_code continueReadPage(Page::span rdbuf) const;
-
-  /// @brief
-  /// 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::span mac) const;
-
-  /// @brief
-  /// Update the status of a memory protection block using the
-  /// Write Page Protection command.
-  /// @param protection
-  /// Desired protection status for the block.
-  /// It is not possible to disable existing protections.
-  MaximInterface_EXPORT error_code
-  writeBlockProtection(BlockProtection protection);
-
-  /// @brief
-  /// Update the status of a memory protection block using the
-  /// Authenticated Write Page Protection command.
-  /// @param newProtection New protection status to write.
-  /// @param[in] mac Write MAC computed for this operation.
-  MaximInterface_EXPORT error_code writeAuthBlockProtection(
-      BlockProtection newProtection, Sha256::Hash::const_span mac);
-
-  /// @brief 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);
-
-  /// @brief 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);
-
-  /// @brief 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(Sleep & sleep, OneWireMaster & master,
-                const SelectRom & selectRom)
-      : selectRom(selectRom), master(&master), sleep(&sleep) {}
-      
-  ~DS28E15_22_25() {}
-
-  error_code doWriteScratchpad(Scratchpad::const_span data, Variant variant);
-
-  error_code doReadScratchpad(Scratchpad::span data, Variant variant) const;
-
-  error_code doReadBlockProtection(int blockNum, BlockProtection & protection,
-                                   Variant variant) const;
-
-  error_code doWriteAuthSegment(int pageNum, int segmentNum,
-                                Segment::const_span newData,
-                                Sha256::Hash::const_span mac, Variant variant);
-
-  error_code doContinueWriteAuthSegment(Segment::const_span newData,
-                                        Sha256::Hash::const_span mac,
-                                        Variant variant);
-
-  error_code doReadAllBlockProtection(span<BlockProtection> protection,
-                                      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(Segment::const_span newData,
-                                Sha256::Hash::const_span mac, Variant variant,
-                                bool continuing);
-
-  error_code writeCommandWithCrc(
-      Command command, uint_least8_t parameter,
-      OneWireMaster::Level level = OneWireMaster::NormalLevel) const;
-
-  SelectRom selectRom;
-  OneWireMaster * master;
-  Sleep * sleep;
-};
-
-inline error_code make_error_code(DS28E15_22_25::ErrorValue e) {
-  return error_code(e, DS28E15_22_25::errorCategory());
-}
-
-/// 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(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
-      : DS28E15_22_25(sleep, master, selectRom) {}
-
-  /// @brief Perform Write Scratchpad operation on the device.
-  /// @param[in] data Data to write to the scratchpad.
-  MaximInterface_EXPORT error_code writeScratchpad(Scratchpad::const_span data);
-
-  /// @brief 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::span data) const;
-
-  /// @brief
-  /// 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;
-
-  /// @brief 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, Segment::const_span newData,
-                   Sha256::Hash::const_span mac);
-
-  /// @brief 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(
-      Segment::const_span newData, Sha256::Hash::const_span mac);
-
-  /// @brief
-  /// 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(
-      span<BlockProtection, protectionBlocks> protection) const;
-};
-
-/// Interface to the DS28E15 authenticator.
-class DS28E15 : public DS28EL15 {
-public:
-  DS28E15(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
-      : DS28EL15(sleep, master, selectRom) {}
-
-  /// @brief 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);
-
-  /// @brief 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(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
-      : DS28E15_22_25(sleep, master, selectRom) {}
-
-  /// @brief Perform Write Scratchpad operation on the device.
-  /// @param[in] data Data to write to the scratchpad.
-  MaximInterface_EXPORT error_code writeScratchpad(Scratchpad::const_span data);
-
-  /// @brief 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::span data) const;
-
-  /// @brief
-  /// 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;
-
-  /// @brief 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, Segment::const_span newData,
-                   Sha256::Hash::const_span mac);
-
-  /// @brief 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(
-      Segment::const_span newData, Sha256::Hash::const_span mac);
-
-  /// @brief
-  /// 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(
-      span<BlockProtection, protectionBlocks> protection) const;
-};
-
-/// Interface to the DS28E22 authenticator.
-class DS28E22 : public DS28EL22 {
-public:
-  DS28E22(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
-      : DS28EL22(sleep, master, selectRom) {}
-
-  /// @brief 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);
-
-  /// @brief 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(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
-      : DS28E15_22_25(sleep, master, selectRom) {}
-
-  /// @brief Perform Write Scratchpad operation on the device.
-  /// @param[in] data Data to write to the scratchpad.
-  MaximInterface_EXPORT error_code writeScratchpad(Scratchpad::const_span data);
-
-  /// @brief 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::span data) const;
-
-  /// @brief
-  /// 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, Segment::const_span newData,
-                   Sha256::Hash::const_span mac);
-
-  /// @brief 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(
-      Segment::const_span newData, Sha256::Hash::const_span mac);
-
-  /// @brief
-  /// 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(
-      span<BlockProtection, protectionBlocks> protection) const;
-};
-
-/// Interface to the DS28E25 authenticator.
-class DS28E25 : public DS28EL25 {
-public:
-  DS28E25(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
-      : DS28EL25(sleep, master, selectRom) {}
-
-  /// @brief 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);
-
-  /// @brief 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);
-};
-
-/// Represents the status of a memory protection block.
-class DS28E15_22_25::BlockProtection {
-public:
-  explicit BlockProtection(uint_least8_t status = 0x00) : status(status) {}
-
-  /// Get the byte representation used by the device.
-  uint_least8_t statusByte() const { return status; }
-  
-  /// Set the byte representation used by the device.
-  BlockProtection & setStatusByte(uint_least8_t status) {
-    this->status = status;
-    return *this;
-  }
-
-  /// 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 BlockProtection & setBlockNum(int blockNum);
-
-  /// @brief 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 BlockProtection &
-  setReadProtection(bool readProtection);
-
-  /// @brief 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 BlockProtection &
-  setWriteProtection(bool writeProtection);
-
-  /// @brief 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 BlockProtection &
-  setEepromEmulation(bool eepromEmulation);
-
-  /// @brief 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 BlockProtection &
-  setAuthProtection(bool authProtection);
-
-  /// @brief Check if no protection options are enabled.
-  /// @returns True if no protection options are enabled.
-  MaximInterface_EXPORT bool noProtection() const;
-
-private:
-  static const unsigned int readProtectionMask = 0x80,
-                            writeProtectionMask = 0x40,
-                            eepromEmulationMask = 0x20,
-                            authProtectionMask = 0x10,
-                            blockNumMask = 0x0F;
-  uint_least8_t status;
-};
-
-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);
-}
-
-/// Format data to hash for an Authenticated Write to a memory segment.
-class DS28E15_22_25::SegmentWriteMacData {
-public:
-  SegmentWriteMacData() : result_() {}
-
-  /// Formatted data result.
-  Sha256::WriteMacData::const_span result() const { return result_; }
-
-  /// @name ROM ID
-  /// @brief 1-Wire ROM ID of the device.
-  /// @{
-
-  /// Get mutable ROM ID.
-  RomId::span romId() {
-    return make_span(result_).subspan<romIdIdx, RomId::size>();
-  }
-  
-  /// Get immutable ROM ID.
-  RomId::const_span romId() const {
-    return const_cast<SegmentWriteMacData &>(*this).romId();
-  }
-  
-  /// Set ROM ID.
-  SegmentWriteMacData & setRomId(RomId::const_span romId) {
-    copy(romId, this->romId());
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name MAN ID
-  /// @brief Manufacturer ID of the device.
-  /// @{
-  
-  /// Get mutable MAN ID.
-  ManId::span manId() {
-    return make_span(result_).subspan<manIdIdx, ManId::size>();
-  }
-  
-  /// Get immutable MAN ID.
-  ManId::const_span manId() const {
-    return const_cast<SegmentWriteMacData &>(*this).manId();
-  }
-  
-  /// Set MAN ID.
-  SegmentWriteMacData & setManId(ManId::const_span manId) {
-    copy(manId, this->manId());
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name Page number
-  /// @brief Page number for write operation.
-  /// @{
-
-  /// Get page number.
-  int pageNum() const { return result_[pageNumIdx]; }
-  
-  /// Set page number.
-  SegmentWriteMacData & setPageNum(int pageNum) {
-    result_[pageNumIdx] = pageNum;
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name Segment number
-  /// @brief Segment number within page for write operation.
-  /// @{
-  
-  /// Get segment number.
-  int segmentNum() const { return result_[segmentNumIdx]; }
-  
-  /// Set segment number.
-  SegmentWriteMacData & setSegmentNum(int segmentNum) {
-    result_[segmentNumIdx] = segmentNum;
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name Old data
-  /// @brief Existing data contained in the segment.
-  /// @{
-  
-  /// Get mutable old data.
-  Segment::span oldData() {
-    return make_span(result_).subspan<oldDataIdx, Segment::size>();
-  }
-  
-  /// Get immutable old data.
-  Segment::const_span oldData() const {
-    return const_cast<SegmentWriteMacData &>(*this).oldData();
-  }
-  
-  /// Set old data.
-  SegmentWriteMacData & setOldData(Segment::const_span oldData) {
-    copy(oldData, this->oldData());
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name New data
-  /// @brief New data to write to the segment.
-  /// @{
-  
-  /// Get mutable new data.
-  Segment::span newData() {
-    return make_span(result_).subspan<newDataIdx, Segment::size>();
-  }
-  
-  /// Get immutable new data.
-  Segment::const_span newData() const {
-    return const_cast<SegmentWriteMacData &>(*this).newData();
-  }
-  
-  /// Set new data.
-  SegmentWriteMacData & setNewData(Segment::const_span newData) {
-    copy(newData, this->newData());
-    return *this;
-  }
-  
-  /// @}
-
-private:
-  typedef Sha256::WriteMacData::span::index_type index;
-
-  static const index romIdIdx = 0;
-  static const index manIdIdx = romIdIdx + RomId::size;
-  static const index pageNumIdx = manIdIdx + ManId::size;
-  static const index segmentNumIdx = pageNumIdx + 1;
-  static const index oldDataIdx = segmentNumIdx + 1;
-  static const index newDataIdx = oldDataIdx + Segment::size;
-
-  Sha256::WriteMacData::array result_;
-};
-
-/// Format data to hash for an Authenticated Write to a memory protection block.
-class DS28E15_22_25::ProtectionWriteMacData {
-public:
-  MaximInterface_EXPORT ProtectionWriteMacData();
-
-  /// Formatted data result.
-  Sha256::WriteMacData::const_span result() const { return result_; }
-
-  /// @name ROM ID
-  /// @brief 1-Wire ROM ID of the device.
-  /// @{
-  
-  /// Get mutable ROM ID.
-  RomId::span romId() {
-    return make_span(result_).subspan<romIdIdx, RomId::size>();
-  }
-  
-  /// Get immutable ROM ID.
-  RomId::const_span romId() const {
-    return const_cast<ProtectionWriteMacData &>(*this).romId();
-  }
-  
-  /// Set ROM ID.
-  ProtectionWriteMacData & setRomId(RomId::const_span romId) {
-    copy(romId, this->romId());
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name MAN ID
-  /// @brief Manufacturer ID of the device.
-  /// @{
-  
-  /// Get mutable MAN ID.
-  ManId::span manId() {
-    return make_span(result_).subspan<manIdIdx, ManId::size>();
-  }
-  
-  /// Get immutable MAN ID.
-  ManId::const_span manId() const {
-    return const_cast<ProtectionWriteMacData &>(*this).manId();
-  }
-  
-  /// Set MAN ID.
-  ProtectionWriteMacData & setManId(ManId::const_span manId) {
-    copy(manId, this->manId());
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name Old protection
-  /// @brief Existing protection status in device.
-  /// @{
-  
-  /// Get old protection.
-  BlockProtection oldProtection() const { return oldProtection_; }
-  
-  /// Set old protection.
-  MaximInterface_EXPORT ProtectionWriteMacData &
-  setOldProtection(BlockProtection oldProtection);
-  
-  /// @}
-
-  /// @name New protection
-  /// @brief New protection status to write.
-  /// @{
-  
-  /// Get new protection.
-  BlockProtection newProtection() const { return newProtection_; }
-  
-  /// Set new protection.
-  MaximInterface_EXPORT ProtectionWriteMacData &
-  setNewProtection(BlockProtection newProtection);
-  
-  /// @}
-
-private:
-  typedef Sha256::WriteMacData::span::index_type index;
-
-  static const index romIdIdx = 0;
-  static const index manIdIdx = romIdIdx + RomId::size;
-  static const index blockNumIdx = manIdIdx + ManId::size;
-  static const index oldProtectionIdx = blockNumIdx + 2;
-  static const index newProtectionIdx = oldProtectionIdx + 4;
-
-  Sha256::WriteMacData::array result_;
-  BlockProtection oldProtection_;
-  BlockProtection newProtection_;
-};
-
-/// @brief
-/// Format data to hash for device authentication or computing the next secret
-/// from the existing secret.
-class DS28E15_22_25::AuthenticationData {
-public:
-  AuthenticationData() : result_() {}
-
-  /// Formatted data result.
-  Sha256::AuthenticationData::const_span result() const { return result_; }
-
-  /// @name Page
-  /// @brief Data from a device memory page.
-  /// @{
-  
-  /// Get mutable page.
-  Page::span page() {
-    return make_span(result_).subspan<pageIdx, Page::size>();
-  }
-  
-  /// Get immutable page.
-  Page::const_span page() const {
-    return const_cast<AuthenticationData &>(*this).page();
-  }
-  
-  /// Set page.
-  AuthenticationData & setPage(Page::const_span page) {
-    copy(page, this->page());
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name Scratchpad
-  /// @brief
-  /// Data from device scratchpad used as a random challenge in device
-  /// authentication and a partial secret in secret computation.
-  /// @{
-
-  /// Get mutable scratchpad.
-  Scratchpad::span scratchpad() {
-    return make_span(result_).subspan<scratchpadIdx, Scratchpad::size>();
-  }
-  
-  /// Get immutable scratchpad.
-  Scratchpad::const_span scratchpad() const {
-    return const_cast<AuthenticationData &>(*this).scratchpad();
-  }
-  
-  /// Set scratchpad.
-  AuthenticationData & setScratchpad(Scratchpad::const_span scratchpad) {
-    copy(scratchpad, this->scratchpad());
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name ROM ID
-  /// @brief 1-Wire ROM ID of the device.
-  /// @{
-  
-  /// Get mutable ROM ID.
-  RomId::span romId() {
-    return make_span(result_).subspan<romIdIdx, RomId::size>();
-  }
-  
-  /// Get immutable ROM ID.
-  RomId::const_span romId() const {
-    return const_cast<AuthenticationData &>(*this).romId();
-  }
-  
-  /// Set ROM ID.
-  AuthenticationData & setRomId(RomId::const_span romId) {
-    copy(romId, this->romId());
-    return *this;
-  }
-  
-  /// Set ROM ID for use in anonymous mode.
-  MaximInterface_EXPORT AuthenticationData & setAnonymousRomId();
-  
-  /// @}
-
-  /// @name MAN ID
-  /// @brief Manufacturer ID of the device.
-  /// @{
-  
-  /// Get mutable MAN ID.
-  ManId::span manId() {
-    return make_span(result_).subspan<manIdIdx, ManId::size>();
-  }
-  
-  /// Get immutable MAN ID.
-  ManId::const_span manId() const {
-    return const_cast<AuthenticationData &>(*this).manId();
-  }
-  
-  /// Set MAN ID.
-  AuthenticationData & setManId(ManId::const_span manId) {
-    copy(manId, this->manId());
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name Page number
-  /// @brief Number of the page to use data from.
-  /// @{
-  
-  /// Get page number.
-  int pageNum() const { return result_[pageNumIdx]; }
-  
-  /// Set page number.
-  AuthenticationData & setPageNum(int pageNum) {
-    result_[pageNumIdx] = pageNum;
-    return *this;
-  }
-  
-  /// @}
-
-private:
-  typedef Sha256::AuthenticationData::span::index_type index;
-
-  static const index pageIdx = 0;
-  static const index scratchpadIdx = pageIdx + Page::size;
-  static const index romIdIdx = scratchpadIdx + Scratchpad::size;
-  static const index manIdIdx = romIdIdx + RomId::size;
-  static const index pageNumIdx = manIdIdx + ManId::size;
-
-  Sha256::AuthenticationData::array result_;
-};
-
-} // namespace MaximInterface
-
-#endif
--- a/Devices/DS28E17.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,270 +0,0 @@
-/*******************************************************************************
-* 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,
-                                      span<const uint_least8_t> data,
-                                      uint_least8_t * wr_status) {
-  return sendPacket(WriteDataWithStopCmd, &I2C_addr, data,
-                    span<uint_least8_t>(), wr_status);
-}
-
-error_code DS28E17::writeDataNoStop(uint_least8_t I2C_addr,
-                                    span<const uint_least8_t> data,
-                                    uint_least8_t * wr_status) {
-  return sendPacket(WriteDataNoStopCmd, &I2C_addr, data, span<uint_least8_t>(),
-                    wr_status);
-}
-
-error_code DS28E17::writeDataOnly(span<const uint_least8_t> data,
-                                  uint_least8_t * wr_status) {
-  return sendPacket(WriteDataOnlyCmd, NULL, data, span<uint_least8_t>(),
-                    wr_status);
-}
-
-error_code DS28E17::writeDataOnlyWithStop(span<const uint_least8_t> data,
-                                          uint_least8_t * wr_status) {
-  return sendPacket(WriteDataOnlyWithStopCmd, NULL, data, span<uint_least8_t>(),
-                    wr_status);
-}
-
-error_code DS28E17::writeReadDataWithStop(uint_least8_t I2C_addr,
-                                          span<const uint_least8_t> write_data,
-                                          span<uint_least8_t> read_data,
-                                          uint_least8_t * wr_status) {
-  return sendPacket(WriteReadDataWithStopCmd, &I2C_addr, write_data, read_data,
-                    wr_status);
-}
-
-error_code DS28E17::readDataWithStop(uint_least8_t I2C_addr,
-                                     span<uint_least8_t> data) {
-  return sendPacket(ReadDataWithStopCmd, &I2C_addr, span<const uint_least8_t>(),
-                    data, 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);
-  }
-  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,
-                               span<const uint_least8_t> write_data,
-                               span<uint_least8_t> read_data,
-                               uint_least8_t * wr_status) {
-  const int pollLimit = 10000;
-  const span<const uint_least8_t>::index_type maxDataLen = 255;
-
-  if ((!write_data.empty() && write_data.size() > maxDataLen) ||
-      (!read_data.empty() && read_data.size() > 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.empty()) {
-    crc16 = calculateCrc16(static_cast<uint_fast8_t>(write_data.size()), crc16);
-    result = master->writeByte(static_cast<uint_least8_t>(write_data.size()));
-    if (result) {
-      return result;
-    }
-    crc16 = calculateCrc16(write_data, crc16);
-    result = master->writeBlock(write_data);
-    if (result) {
-      return result;
-    }
-  }
-  if (!read_data.empty()) {
-    crc16 = calculateCrc16(static_cast<uint_fast8_t>(read_data.size()), crc16);
-    result = master->writeByte(static_cast<uint_least8_t>(read_data.size()));
-    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);
-  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.empty()) {
-    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.empty()) {
-    result = master->readBlock(read_data);
-  }
-  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
--- a/Devices/DS28E17.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,205 +0,0 @@
-/*******************************************************************************
-* 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>
-#include <MaximInterface/Utilities/span.hpp>
-
-namespace MaximInterface {
-
-/// @brief 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;
-  }
-
-  /// @brief 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 with length 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, span<const uint_least8_t> data,
-                    uint_least8_t * wr_status = NULL);
-
-  /// @brief 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 with length 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, span<const uint_least8_t> data,
-                  uint_least8_t * wr_status = NULL);
-
-  /// @brief Write Data Only command.
-  /// @details Output on I2C: Write Data [1-255]
-  /// @param[in] data I2C data to write with length 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(span<const uint_least8_t> data,
-                uint_least8_t * wr_status = NULL);
-
-  /// @brief Write Data Only With Stop command.
-  /// @details Output on I2C: Write Data [1-255], P
-  /// @param[in] data I2C data to write with length 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(span<const uint_least8_t> data,
-                        uint_least8_t * wr_status = NULL);
-
-  /// @brief 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 with length 1-255.
-  /// @param[out] read_data I2C data that was read with length 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, span<const uint_least8_t> write_data,
-      span<uint_least8_t> read_data, uint_least8_t * wr_status = NULL);
-
-  /// @brief 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 with length 1-255.
-  MaximInterface_EXPORT error_code readDataWithStop(uint_least8_t I2C_addr,
-                                                    span<uint_least8_t> data);
-
-  /// Write to Configuration Register of DS28E17.
-  MaximInterface_EXPORT error_code writeConfigReg(I2CSpeed speed);
-
-  /// @brief Read the Configuration Register of DS28E17.
-  /// @param[out] speed Speed read from configuration register.
-  MaximInterface_EXPORT error_code readConfigReg(I2CSpeed & speed);
-
-  /// @brief Put 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();
-
-  /// @brief 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,
-                        span<const uint_least8_t> write_data,
-                        span<uint_least8_t> read_data,
-                        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
--- a/Devices/DS28E38.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,302 +0,0 @@
-/*******************************************************************************
-* 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 <algorithm>
-#include <MaximInterface/Utilities/Algorithm.hpp>
-#include <MaximInterface/Utilities/Error.hpp>
-#include "DS28E38.hpp"
-
-namespace MaximInterface {
-
-using std::copy;
-
-static const int readMemoryTimeMs = 30;
-static const int writeMemoryTimeMs = 65;
-static const int writeStateTimeMs = 15;
-static const int generateEccKeyPairTimeMs = 200;
-static const int generateEcdsaSignatureTimeMs = 130;
-static const int trngOnDemandCheckTimeMs = 20;
-static const int trngGenerationTimeMs = 10;
-
-const int DS28E38::decrementCounterPage;
-const int DS28E38::publicKeyXPage;
-const int DS28E38::publicKeyYPage;
-const int DS28E38::privateKeyPage;
-const int DS28E38::memoryPages;
-
-error_code DS28E38::writeMemory(int pageNum, Page::const_span page) {
-  if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
-  }
-
-  uint_least8_t command[2 + Page::size];
-  command[0] = 0x96;
-  command[1] = pageNum;
-  copy(page.begin(), page.end(), command + 2);
-  return runCommand(command, writeMemoryTimeMs);
-}
-
-error_code DS28E38::readMemory(int pageNum, Page::span page) {
-  if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
-  }
-
-  uint_least8_t buffer[1 + Page::size];
-  buffer[0] = 0x44;
-  buffer[1] = pageNum;
-  span<uint_least8_t> response(buffer);
-  const error_code result =
-      runCommand(make_span(buffer, 2), readMemoryTimeMs, response);
-  if (!result) {
-    copy(response.begin(), response.end(), page.begin());
-  }
-  return result;
-}
-
-error_code DS28E38::readStatus(bool entropyHealthTest, Status & status) {
-  int delay = readMemoryTimeMs;
-  if (entropyHealthTest) {
-    delay += trngOnDemandCheckTimeMs;
-  }
-  uint_least8_t buffer[Status::PageProtectionList::csize + ManId::size +
-                       Status::RomVersion::csize + 2];
-  buffer[0] = 0xAA;
-  buffer[1] = entropyHealthTest ? 0x01 : 0x00;
-  span<uint_least8_t> response(buffer);
-  error_code result = runCommand(make_span(buffer, 2), delay, response);
-  if (!result) {
-    span<uint_least8_t>::const_iterator responseIt = response.begin();
-    for (Status::PageProtectionList::iterator it =
-             status.pageProtection.begin();
-         it != status.pageProtection.end(); ++it) {
-      *it = *responseIt;
-      ++responseIt;
-    }
-    span<uint_least8_t>::const_iterator responseItEnd =
-        responseIt + status.manId.size();
-    copy(responseIt, responseItEnd, status.manId.begin());
-    responseIt = responseItEnd;
-    responseItEnd = responseIt + status.romVersion.size();
-    copy(responseIt, responseItEnd, status.romVersion.begin());
-    responseIt = responseItEnd;
-    switch (*responseIt) {
-    case Status::TestNotPerformed:
-    case Status::EntropyHealthy:
-    case Status::EntropyNotHealthy:
-      status.entropyHealthTestStatus =
-          static_cast<Status::EntropyHealthTestStatus>(*responseIt);
-      break;
-
-    default:
-      result = make_error_code(InvalidResponseError);
-      break;
-    }
-  }
-  return result;
-}
-
-error_code DS28E38::setPageProtection(int pageNum,
-                                      const PageProtection & protection) {
-  if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
-  }
-
-  int delay = writeStateTimeMs;
-  if (pageNum == decrementCounterPage) {
-    delay += writeMemoryTimeMs;
-  }
-  const uint_least8_t command[] = {
-      0xC3, static_cast<uint_least8_t>(pageNum),
-      static_cast<uint_least8_t>(protection.to_ulong())};
-  return runCommand(command, delay);
-}
-
-error_code
-DS28E38::computeAndReadPageAuthentication(int pageNum, bool anonymous,
-                                          Page::const_span challenge,
-                                          Ecc256::Signature::span signature) {
-  if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
-  }
-
-  const size_t commandSize = 2 + Page::size;
-  const size_t responseSize = 1 + 2 * Ecc256::Scalar::size;
-  uint_least8_t buffer[MaximInterface_MAX(commandSize, responseSize)];
-  buffer[0] = 0xA5;
-  buffer[1] = pageNum | (anonymous ? 0xE0 : 0x00);
-  copy(challenge.begin(), challenge.end(), buffer + 2);
-  span<uint_least8_t> response(buffer, responseSize);
-  const error_code result = runCommand(make_span(buffer, commandSize),
-                                       generateEcdsaSignatureTimeMs, response);
-  if (!result) {
-    span<uint_least8_t>::const_iterator begin = response.begin();
-    span<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 DS28E38::decrementCounter() {
-  const uint_least8_t command = 0xC9;
-  return runCommand(make_span(&command, 1), writeMemoryTimeMs);
-}
-
-error_code DS28E38::disableDevice() {
-  const uint_least8_t command[] = {0x33, 0x9E, 0xA7, 0x49, 0xFB,
-                                   0x10, 0x62, 0x0A, 0x26};
-  return runCommand(command, writeStateTimeMs);
-}
-
-error_code DS28E38::generateEcc256KeyPair(bool privateKeyPuf,
-                                          bool writeProtectEnable) {
-  int delay = generateEccKeyPairTimeMs;
-  if (writeProtectEnable) {
-    delay += writeStateTimeMs;
-  }
-  uint_least8_t command[] = {0xCB, 0x00};
-  if (privateKeyPuf) {
-    command[1] |= 0x01;
-  }
-  if (writeProtectEnable) {
-    command[1] |= 0x80;
-  }
-  return runCommand(command, delay);
-}
-
-error_code DS28E38::readRng(span<uint_least8_t> data) {
-  const span<uint_least8_t>::index_type maxDataSize = 64;
-  if ((data.size() < 1) || (data.size() > maxDataSize)) {
-    return make_error_code(InvalidParameterError);
-  }
-
-  uint_least8_t buffer[1 + maxDataSize];
-  buffer[0] = 0xD2;
-  buffer[1] = data.size() - 1;
-  span<uint_least8_t> response(buffer, 1 + data.size());
-  const error_code result =
-      runCommand(make_span(buffer, 2), trngGenerationTimeMs, response);
-  if (!result) {
-    copy(response.begin(), response.end(), data.begin());
-  }
-  return result;
-}
-
-error_code DS28E38::runCommand(span<const uint_least8_t> command, int delayTime,
-                               span<uint_least8_t> & response) {
-  const span<const uint_least8_t>::index_type responseInputSize =
-      response.size();
-  error_code result = doRunCommand(command, delayTime, response);
-  if (result) {
-    return result;
-  }
-  if (response.empty()) {
-    return make_error_code(InvalidResponseError);
-  }
-  // Parse command result byte.
-  switch (response[0]) {
-  case 0xAA:
-    // Success response.
-    if (response.size() != responseInputSize) {
-      result = make_error_code(InvalidResponseError);
-    }
-    break;
-
-  case 0x00:
-    result = make_error_code(InvalidResponseError);
-    break;
-
-  default:
-    result.assign(response[0], errorCategory());
-    break;
-  }
-  response = response.subspan(1);
-  return result;
-}
-
-error_code DS28E38::runCommand(span<const uint_least8_t> command,
-                               int delayTime) {
-  uint_least8_t buffer;
-  span<uint_least8_t> response(&buffer, 1);
-  return runCommand(command, delayTime, response);
-}
-
-const error_category & DS28E38::errorCategory() {
-  static class : public error_category {
-  public:
-    virtual const char * name() const { return "DS28E38"; }
-
-    virtual std::string message(int condition) const {
-      switch (condition) {
-      case InvalidOperationError:
-        return "Invalid Operation Error";
-
-      case InvalidParameterError:
-        return "Invalid Parameter Error";
-
-      case InvalidSequenceError:
-        return "Invalid Sequence Error";
-
-      case InternalError:
-        return "Internal Error";
-
-      case DeviceDisabledError:
-        return "Device Disabled Error";
-
-      case InvalidResponseError:
-        return "Invalid Response Error";
-      }
-      return defaultErrorMessage(condition);
-    }
-  } instance;
-  return instance;
-}
-
-error_code readManId(DS28E38 & ds28e38, ManId::span manId) {
-  DS28E38::Status status;
-  const error_code result = ds28e38.readStatus(false, status);
-  if (!result) {
-    copy(make_span(status.manId), manId);
-  }
-  return result;
-}
-
-DS28E38::PageAuthenticationData &
-DS28E38::PageAuthenticationData::setAnonymousRomId() {
-  std::fill(romId().begin(), romId().end(), 0xFF);
-  return *this;
-}
-
-} // namespace MaximInterface
--- a/Devices/DS28E38.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,316 +0,0 @@
-/*******************************************************************************
-* 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_DS28E38
-#define MaximInterface_DS28E38
-
-#include <stdint.h>
-#include <MaximInterface/Links/RunCommand.hpp>
-#include <MaximInterface/Utilities/array_span.hpp>
-#include <MaximInterface/Utilities/Ecc256.hpp>
-#include <MaximInterface/Utilities/Export.h>
-#include <MaximInterface/Utilities/FlagSet.hpp>
-#include <MaximInterface/Utilities/ManId.hpp>
-#include <MaximInterface/Utilities/system_error.hpp>
-
-namespace MaximInterface {
-
-class DS28E38 {
-public:
-  /// Device command results.
-  enum ErrorValue {
-    InvalidOperationError = 0x55,
-    InvalidParameterError = 0x77,
-    InvalidSequenceError = 0x33,
-    InternalError = 0x22,
-    DeviceDisabledError = 0x88,
-    InvalidResponseError =
-        0x100 ///< Command response does not match expected format.
-  };
-
-  /// @name Device memory pages
-  /// @{
-  
-  static const int decrementCounterPage = 3;
-  static const int publicKeyXPage = 4;
-  static const int publicKeyYPage = 5;
-  static const int privateKeyPage = 6;
-  
-  /// @}
-
-  static const int memoryPages = 7;
-
-  /// Holds a device memory page.
-  typedef array_span<uint_least8_t, 32> Page;
-
-  // Format page authentication input data.
-  class PageAuthenticationData;
-
-  /// Page protection types.
-  enum PageProtectionType {
-    RP = 0x01, ///< Read protection.
-    WP = 0x02, ///< Write protection.
-    EM = 0x04, ///< EPROM emulation mode.
-    DC = 0x08, ///< Decrement counter.
-    PF = 0x10  ///< PUF used as private key.
-  };
-  typedef FlagSet<PageProtectionType, 5> PageProtection;
-
-  struct Status {
-    enum EntropyHealthTestStatus {
-      TestNotPerformed = 0xFF,
-      EntropyHealthy = 0xAA,
-      EntropyNotHealthy = 0xDD
-    };
-
-    typedef array<PageProtection, memoryPages> PageProtectionList;
-    typedef array<uint_least8_t, 2> RomVersion;
-
-    PageProtectionList pageProtection;
-    ManId::array manId;
-    RomVersion romVersion;
-    EntropyHealthTestStatus entropyHealthTestStatus;
-  };
-
-  explicit DS28E38(const RunCommand & runCommand) : doRunCommand(runCommand) {}
-
-  void setRunCommand(const RunCommand & runCommand) {
-    doRunCommand = runCommand;
-  }
-
-  /// @brief Write memory with no protection.
-  /// @param pageNum Number of page to write.
-  /// @param page Data to write.
-  MaximInterface_EXPORT error_code writeMemory(int pageNum,
-                                               Page::const_span page);
-
-  /// @brief 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::span page);
-
-  /// @brief
-  /// Reads the current status of the device and optionally performs an
-  /// entropy health test.
-  /// @param entropyHealthTest True to perform an entropy health test.
-  /// @param[out] status Status that was read.
-  MaximInterface_EXPORT error_code readStatus(bool entropyHealthTest,
-                                              Status & status);
-
-  /// @brief 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);
-
-  /// @brief Compute and read page authentication with ECDSA.
-  /// @param pageNum Number of page to authenticate.
-  /// @param anonymous True to disable use of ROM ID in computation.
-  /// @param challenge Random challenge used to prevent replay attacks.
-  /// @param[out] signature Computed page signature.
-  MaximInterface_EXPORT error_code computeAndReadPageAuthentication(
-      int pageNum, bool anonymous, Page::const_span challenge,
-      Ecc256::Signature::span signature);
-
-  /// Decrement the decrement-only counter.
-  MaximInterface_EXPORT error_code decrementCounter();
-
-  /// Permanently disable the device.
-  MaximInterface_EXPORT error_code disableDevice();
-
-  /// @brief Generate a new ECDSA public key from an existing private key.
-  /// @param privateKeyPuf True if PUF is used as the private key.
-  /// @param writeProtectEnable True to lock the key against further writes.
-  MaximInterface_EXPORT error_code
-  generateEcc256KeyPair(bool privateKeyPuf, bool writeProtectEnable);
-
-  /// @brief Read a block of random data from the RNG.
-  /// @param[out] data Random data from RNG with length from 1 to 64.
-  MaximInterface_EXPORT error_code readRng(span<uint_least8_t> data);
-
-  MaximInterface_EXPORT static const error_category & errorCategory();
-
-protected:
-  MaximInterface_EXPORT error_code runCommand(span<const uint_least8_t> command,
-                                              int delayTime,
-                                              span<uint_least8_t> & response);
-
-  MaximInterface_EXPORT error_code runCommand(span<const uint_least8_t> command,
-                                              int delayTime);
-
-private:
-  RunCommand doRunCommand;
-};
-
-inline error_code make_error_code(DS28E38::ErrorValue e) {
-  return error_code(e, DS28E38::errorCategory());
-}
-
-/// @brief Read the device MAN ID using the Read Status command.
-/// @param ds28e38 Device to read.
-/// @param[out] manId Read MAN ID valid when operation is successful.
-MaximInterface_EXPORT error_code readManId(DS28E38 & ds28e38,
-                                           ManId::span manId);
-
-/// Format page authentication input data.
-class DS28E38::PageAuthenticationData {
-public:
-  typedef array_span<uint_least8_t,
-                     RomId::size + 2 * Page::size + 1 + ManId::size>
-      Result;
-
-  PageAuthenticationData() : result_() {}
-
-  /// Formatted data result.
-  Result::const_span result() const { return result_; }
-
-  /// @name ROM ID
-  /// @brief 1-Wire ROM ID of the device.
-  /// @{
-  
-  /// Get mutable ROM ID.
-  RomId::span romId() {
-    return make_span(result_).subspan<romIdIdx, RomId::size>();
-  }
-  
-  /// Get immutable ROM ID.
-  RomId::const_span romId() const {
-    return const_cast<PageAuthenticationData &>(*this).romId();
-  }
-  
-  /// Set ROM ID.
-  PageAuthenticationData & setRomId(RomId::const_span romId) {
-    copy(romId, this->romId());
-    return *this;
-  }
-  
-  /// Set ROM ID for use in anonymous mode.
-  MaximInterface_EXPORT PageAuthenticationData & setAnonymousRomId();
-  
-  /// @}
-
-  /// @name Page
-  /// @brief Data from a device memory page.
-  /// @{
-  
-  /// Get mutable page.
-  Page::span page() {
-    return make_span(result_).subspan<pageIdx, Page::size>();
-  }
-  
-  /// Get immutable page.
-  Page::const_span page() const {
-    return const_cast<PageAuthenticationData &>(*this).page();
-  }
-  
-  /// Set page.
-  PageAuthenticationData & setPage(Page::const_span page) {
-    copy(page, this->page());
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name Challenge
-  /// @brief Random challenge used to prevent replay attacks.
-  /// @{
-
-  /// Get mutable Challenge.
-  Page::span challenge() {
-    return make_span(result_).subspan<challengeIdx, Page::size>();
-  }
-  
-  /// Get immutable Challenge.
-  Page::const_span challenge() const {
-    return const_cast<PageAuthenticationData &>(*this).challenge();
-  }
-  
-  /// Set Challenge.
-  PageAuthenticationData & setChallenge(Page::const_span challenge) {
-    copy(challenge, this->challenge());
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name Page number
-  /// @brief Number of the page to use data from.
-  /// @{
-  
-  /// Get page number.
-  int pageNum() const { return result_[pageNumIdx]; }
-  
-  /// Set page number.
-  PageAuthenticationData & setPageNum(int pageNum) {
-    result_[pageNumIdx] = pageNum;
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name MAN ID
-  /// @brief Manufacturer ID of the device.
-  /// @{
-  
-  /// Get mutable MAN ID.
-  ManId::span manId() {
-    return make_span(result_).subspan<manIdIdx, ManId::size>();
-  }
-  
-  /// Get immutable MAN ID.
-  ManId::const_span manId() const {
-    return const_cast<PageAuthenticationData &>(*this).manId();
-  }
-  
-  /// Set MAN ID.
-  PageAuthenticationData & setManId(ManId::const_span manId) {
-    copy(manId, this->manId());
-    return *this;
-  }
-  
-  /// @}
-
-private:
-  typedef Result::span::index_type index;
-
-  static const index romIdIdx = 0;
-  static const index pageIdx = romIdIdx + RomId::size;
-  static const index challengeIdx = pageIdx + Page::size;
-  static const index pageNumIdx = challengeIdx + Page::size;
-  static const index manIdIdx = pageNumIdx + 1;
-
-  Result::array result_;
-};
-
-} // namespace MaximInterface
-
-#endif
--- a/Devices/DS9400.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*******************************************************************************
-* 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::waitAwake() {
-  error_code result;
-  uint_least8_t data;
-  do {
-    result = uart->readByte(data);
-  } while (!result && data != 0xA5);
-  return result;
-}
-
-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);
-    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;
-}
-
-error_code DS9400::configure(uint_least8_t config) {
-  const uint_least8_t packet[] = {'C', config};
-  return uart->writeBlock(packet);
-}
-
-} // namespace MaximInterface
--- a/Devices/DS9400.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*******************************************************************************
-* 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 waitAwake();
-
-  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);
-
-protected:
-  MaximInterface_EXPORT error_code configure(uint_least8_t config);
-
-private:
-  Uart * uart;
-};
-
-} // namespace MaximInterface
-
-#endif
--- a/Devices/DS9481P_300.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,257 +0,0 @@
-/*******************************************************************************
-* 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 "DS9481P_300.hpp"
-
-namespace MaximInterface {
-
-DS9481P_300::DS9481P_300(Sleep & sleep, SerialPort & serialPort)
-    : serialPort(&serialPort), currentBus(OneWire), ds2480b(sleep, serialPort),
-      oneWireMaster_(*this), ds9400(serialPort), i2cMaster_(*this) {}
-
-error_code DS9481P_300::connect(const std::string & portName) {
-  error_code result = serialPort->connect(portName);
-  if (!result) {
-    result = selectOneWire();
-    if (result) {
-      serialPort->disconnect();
-    } else {
-      currentBus = OneWire;
-    }
-  }
-  return result;
-}
-
-error_code DS9481P_300::disconnect() {
-  return serialPort->disconnect();
-}
-
-bool DS9481P_300::connected() const {
-  return serialPort->connected();
-}
-
-std::string DS9481P_300::portName() const {
-  return serialPort->portName();
-}
-
-error_code DS9481P_300::selectOneWire() {
-  // Escape DS9400 mode.
-  error_code result = ds9400.escape();
-  if (!result) {
-    result = ds2480b.initialize();
-  }
-  return result;
-}
-
-error_code DS9481P_300::selectBus(Bus newBus) {
-  error_code result;
-  if (currentBus != newBus) {
-    switch (currentBus) {
-    case OneWire: // Next bus I2C.
-      // Escape DS2480 Mode.
-      result = ds2480b.escape();
-      if (!result) {
-        // Wait for awake notification.
-        result = ds9400.waitAwake();
-      }
-      break;
-
-    case I2C: // Next bus OneWire.
-      result = selectOneWire();
-      break;
-    }
-    if (!result) {
-      currentBus = newBus;
-    }
-  }
-  return result;
-}
-
-error_code DS9481P_300::OneWireMasterImpl::reset() {
-  error_code result = parent->selectBus(OneWire);
-  if (!result) {
-    result = OneWireMasterDecorator::reset();
-  }
-  return result;
-}
-
-error_code DS9481P_300::OneWireMasterImpl::touchBitSetLevel(bool & sendRecvBit,
-                                                            Level afterLevel) {
-  error_code result = parent->selectBus(OneWire);
-  if (!result) {
-    result = OneWireMasterDecorator::touchBitSetLevel(sendRecvBit, afterLevel);
-  }
-  return result;
-}
-
-error_code
-DS9481P_300::OneWireMasterImpl::writeByteSetLevel(uint_least8_t sendByte,
-                                                  Level afterLevel) {
-  error_code result = parent->selectBus(OneWire);
-  if (!result) {
-    result = OneWireMasterDecorator::writeByteSetLevel(sendByte, afterLevel);
-  }
-  return result;
-}
-
-error_code
-DS9481P_300::OneWireMasterImpl::readByteSetLevel(uint_least8_t & recvByte,
-                                                 Level afterLevel) {
-  error_code result = parent->selectBus(OneWire);
-  if (!result) {
-    result = OneWireMasterDecorator::readByteSetLevel(recvByte, afterLevel);
-  }
-  return result;
-}
-
-error_code
-DS9481P_300::OneWireMasterImpl::writeBlock(span<const uint_least8_t> sendBuf) {
-  error_code result = parent->selectBus(OneWire);
-  if (!result) {
-    result = OneWireMasterDecorator::writeBlock(sendBuf);
-  }
-  return result;
-}
-
-error_code
-DS9481P_300::OneWireMasterImpl::readBlock(span<uint_least8_t> recvBuf) {
-  error_code result = parent->selectBus(OneWire);
-  if (!result) {
-    result = OneWireMasterDecorator::readBlock(recvBuf);
-  }
-  return result;
-}
-
-error_code DS9481P_300::OneWireMasterImpl::setSpeed(Speed newSpeed) {
-  error_code result = parent->selectBus(OneWire);
-  if (!result) {
-    result = OneWireMasterDecorator::setSpeed(newSpeed);
-  }
-  return result;
-}
-
-error_code DS9481P_300::OneWireMasterImpl::setLevel(Level newLevel) {
-  error_code result = parent->selectBus(OneWire);
-  if (!result) {
-    result = OneWireMasterDecorator::setLevel(newLevel);
-  }
-  return result;
-}
-
-error_code DS9481P_300::OneWireMasterImpl::triplet(TripletData & data) {
-  error_code result = parent->selectBus(OneWire);
-  if (!result) {
-    result = OneWireMasterDecorator::triplet(data);
-  }
-  return result;
-}
-
-error_code DS9481P_300::I2CMasterImpl::start(uint_least8_t address) {
-  error_code result = parent->selectBus(I2C);
-  if (!result) {
-    result = I2CMasterDecorator::start(address);
-  }
-  return result;
-}
-
-error_code DS9481P_300::I2CMasterImpl::stop() {
-  error_code result = parent->selectBus(I2C);
-  if (!result) {
-    result = I2CMasterDecorator::stop();
-  }
-  return result;
-}
-
-error_code DS9481P_300::I2CMasterImpl::writeByte(uint_least8_t data) {
-  error_code result = parent->selectBus(I2C);
-  if (!result) {
-    result = I2CMasterDecorator::writeByte(data);
-  }
-  return result;
-}
-
-error_code
-DS9481P_300::I2CMasterImpl::writeBlock(span<const uint_least8_t> data) {
-  error_code result = parent->selectBus(I2C);
-  if (!result) {
-    result = I2CMasterDecorator::writeBlock(data);
-  }
-  return result;
-}
-
-error_code DS9481P_300::I2CMasterImpl::writePacketImpl(
-    uint_least8_t address, span<const uint_least8_t> data, bool sendStop) {
-  error_code result = parent->selectBus(I2C);
-  if (!result) {
-    result = I2CMasterDecorator::writePacketImpl(address, data, sendStop);
-  }
-  return result;
-}
-
-error_code DS9481P_300::I2CMasterImpl::readByte(AckStatus status,
-                                                uint_least8_t & data) {
-  error_code result = parent->selectBus(I2C);
-  if (!result) {
-    result = I2CMasterDecorator::readByte(status, data);
-  }
-  return result;
-}
-
-error_code DS9481P_300::I2CMasterImpl::readBlock(AckStatus status,
-                                                 span<uint_least8_t> data) {
-  error_code result = parent->selectBus(I2C);
-  if (!result) {
-    result = I2CMasterDecorator::readBlock(status, data);
-  }
-  return result;
-}
-
-error_code DS9481P_300::I2CMasterImpl::readPacketImpl(uint_least8_t address,
-                                                      span<uint_least8_t> data,
-                                                      bool sendStop) {
-  error_code result = parent->selectBus(I2C);
-  if (!result) {
-    result = I2CMasterDecorator::readPacketImpl(address, data, sendStop);
-  }
-  return result;
-}
-
-error_code DS9481P_300::DS2480BWithEscape::escape() {
-  return sendCommand(0xE5);
-}
-
-error_code DS9481P_300::DS9400WithEscape::escape() {
-  return configure('O');
-}
-
-} // namespace MaximInterface
--- a/Devices/DS9481P_300.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +0,0 @@
-/*******************************************************************************
-* 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_DS9481P_300
-#define MaximInterface_DS9481P_300
-
-#include <MaximInterface/Devices/DS2480B.hpp>
-#include <MaximInterface/Devices/DS9400.hpp>
-#include <MaximInterface/Links/I2CMasterDecorator.hpp>
-#include <MaximInterface/Links/OneWireMasterDecorator.hpp>
-#include <MaximInterface/Links/SerialPort.hpp>
-#include <MaximInterface/Links/Sleep.hpp>
-#include <MaximInterface/Utilities/Export.h>
-
-namespace MaximInterface {
-
-/// DS9481P-300 USB to 1-Wire and I2C adapter.
-class DS9481P_300 {
-public:
-  MaximInterface_EXPORT DS9481P_300(Sleep & sleep, SerialPort & serialPort);
-
-  void setSleep(Sleep & sleep) { ds2480b.setSleep(sleep); }
-  
-  void setSerialPort(SerialPort & serialPort) {
-    this->serialPort = &serialPort;
-    ds2480b.setUart(serialPort);
-    ds9400.setUart(serialPort);
-  }
-
-  MaximInterface_EXPORT error_code connect(const std::string & portName);
-  
-  MaximInterface_EXPORT error_code disconnect();
-  
-  MaximInterface_EXPORT bool connected() const;
-  
-  MaximInterface_EXPORT std::string portName() const;
-
-  /// 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_; }
-
-private:
-  class OneWireMasterImpl : public OneWireMasterDecorator {
-  public:
-    explicit OneWireMasterImpl(DS9481P_300 & parent)
-        : OneWireMasterDecorator(parent.ds2480b), parent(&parent) {}
-
-    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(span<const uint_least8_t> sendBuf);
-    
-    MaximInterface_EXPORT virtual error_code
-    readBlock(span<uint_least8_t> recvBuf);
-    
-    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:
-    DS9481P_300 * parent;
-  };
-
-  class I2CMasterImpl : public I2CMasterDecorator {
-  public:
-    explicit I2CMasterImpl(DS9481P_300 & parent)
-        : I2CMasterDecorator(parent.ds9400), parent(&parent) {}
-
-    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(span<const uint_least8_t> data);
-    
-    MaximInterface_EXPORT virtual error_code readByte(AckStatus status,
-                                                      uint_least8_t & data);
-    MaximInterface_EXPORT virtual error_code
-    readBlock(AckStatus status, span<uint_least8_t> data);
-
-  protected:
-    MaximInterface_EXPORT virtual error_code
-    writePacketImpl(uint_least8_t address, span<const uint_least8_t> data,
-                    bool sendStop);
-                    
-    MaximInterface_EXPORT virtual error_code
-    readPacketImpl(uint_least8_t address, span<uint_least8_t> data,
-                   bool sendStop);
-
-  private:
-    DS9481P_300 * parent;
-  };
-
-  class DS2480BWithEscape : public DS2480B {
-  public:
-    DS2480BWithEscape(Sleep & sleep, Uart & uart) : DS2480B(sleep, uart) {}
-
-    error_code escape();
-  };
-
-  class DS9400WithEscape : public DS9400 {
-  public:
-    explicit DS9400WithEscape(Uart & uart) : DS9400(uart) {}
-
-    error_code escape();
-  };
-
-  enum Bus { OneWire, I2C };
-
-  SerialPort * serialPort;
-  Bus currentBus;
-  DS2480BWithEscape ds2480b;
-  OneWireMasterImpl oneWireMaster_;
-  DS9400WithEscape ds9400;
-  I2CMasterImpl i2cMaster_;
-
-  error_code selectOneWire();
-  error_code selectBus(Bus newBus);
-
-  friend class OneWireMasterImpl;
-  friend class I2CMasterImpl;
-};
-
-} // namespace MaximInterface
-
-#endif
--- a/Links/I2CMaster.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*******************************************************************************
-* 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(span<const uint_least8_t> data) {
-  error_code result;
-  for (span<const uint_least8_t>::index_type i = 0;
-       i < data.size() && !result; ++i) {
-    result = writeByte(data[i]);
-  }
-  return result;
-}
-
-error_code I2CMaster::writePacketImpl(uint_least8_t address,
-                                      span<const uint_least8_t> data,
-                                      bool sendStop) {
-  error_code result = start(address & 0xFE);
-  if (!result) {
-    result = writeBlock(data);
-  }
-  if (sendStop) {
-    error_code stopResult = stop();
-    if (!result) {
-      result = stopResult;
-    }
-  }
-  return result;
-}
-
-error_code I2CMaster::readBlock(AckStatus status, span<uint_least8_t> data) {
-  error_code result;
-  for (span<uint_least8_t>::index_type i = 0; i < data.size() && !result; ++i) {
-    result = readByte(i == (data.size() - 1) ? status : Ack, data[i]);
-  }
-  return result;
-}
-
-error_code I2CMaster::readPacketImpl(uint_least8_t address,
-                                     span<uint_least8_t> data, bool sendStop) {
-  error_code result = start(address | 0x01);
-  if (!result) {
-    result = readBlock(Nack, data);
-  }
-  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
--- a/Links/I2CMaster.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*******************************************************************************
-* 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 <stdint.h>
-#include <MaximInterface/Utilities/Export.h>
-#include <MaximInterface/Utilities/span.hpp>
-#include <MaximInterface/Utilities/system_error.hpp>
-
-namespace MaximInterface {
-
-/// I2C master interface.
-class I2CMaster {
-public:
-  enum ErrorValue {
-    NackError = 1 ///< Transaction stopped due to a NACK from the slave device.
-  };
-
-  enum AckStatus { Nack, Ack };
-
-  virtual ~I2CMaster() {}
-
-  /// @brief Send start condition and address on the bus.
-  /// @param address Address with R/W bit.
-  virtual error_code start(uint_least8_t address) = 0;
-  
-  /// Send stop condition on the bus.
-  virtual error_code stop() = 0;
-  
-  /// Write data byte to the bus.
-  virtual error_code writeByte(uint_least8_t data) = 0;
-  
-  /// Write data block to the bus.
-  MaximInterface_EXPORT virtual error_code
-  writeBlock(span<const uint_least8_t> data);
-  
-  /// @brief
-  /// Perform a complete write transaction on the bus with optional stop
-  /// condition.
-  /// @param address Address in 8-bit format.
-  /// @param data Data to write to the bus.
-  /// @param sendStop
-  /// True to send a stop condition or false to set up a repeated start.
-  error_code writePacket(uint_least8_t address, span<const uint_least8_t> data,
-                         bool sendStop = true) {
-    return writePacketImpl(address, data, sendStop);
-  }
-  
-  /// @brief Read data byte from the bus.
-  /// @param status Determines whether an ACK or NACK is sent after reading.
-  /// @param[out] data Data read from the bus if successful.
-  virtual error_code readByte(AckStatus status, uint_least8_t & data) = 0;
-  
-  /// @brief Read data block from the bus.
-  /// @param status Determines whether an ACK or NACK is sent after reading.
-  /// @param[out] data Data read from the bus if successful.
-  MaximInterface_EXPORT virtual error_code
-  readBlock(AckStatus status, span<uint_least8_t> data);
-  
-  /// @brief
-  /// Perform a complete read transaction on the bus with optional stop
-  /// condition.
-  /// @param address Address in 8-bit format.
-  /// @param[out] data Data read from the bus if successful.
-  /// @param sendStop
-  /// True to send a stop condition or false to set up a repeated start.
-  error_code readPacket(uint_least8_t address, span<uint_least8_t> data,
-                        bool sendStop = true) {
-    return readPacketImpl(address, data, sendStop);
-  }
-
-  MaximInterface_EXPORT static const error_category & errorCategory();
-
-protected:
-  MaximInterface_EXPORT virtual error_code
-  writePacketImpl(uint_least8_t address, span<const uint_least8_t> data,
-                  bool sendStop);
- 
-  MaximInterface_EXPORT virtual error_code
-  readPacketImpl(uint_least8_t address, span<uint_least8_t> data,
-                 bool sendStop);
-};
-
-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
--- a/Links/I2CMasterDecorator.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*******************************************************************************
-* 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 master->start(address);
-}
-
-error_code I2CMasterDecorator::stop() { return master->stop(); }
-
-error_code I2CMasterDecorator::writeByte(uint_least8_t data) {
-  return master->writeByte(data);
-}
-
-error_code I2CMasterDecorator::writeBlock(span<const uint_least8_t> data) {
-  return master->writeBlock(data);
-}
-
-error_code I2CMasterDecorator::writePacketImpl(uint_least8_t address,
-                                               span<const uint_least8_t> data,
-                                               bool sendStop) {
-  return master->writePacket(address, data, sendStop);
-}
-
-error_code I2CMasterDecorator::readByte(AckStatus status,
-                                        uint_least8_t & data) {
-  return master->readByte(status, data);
-}
-
-error_code I2CMasterDecorator::readBlock(AckStatus status,
-                                         span<uint_least8_t> data) {
-  return master->readBlock(status, data);
-}
-
-error_code I2CMasterDecorator::readPacketImpl(uint_least8_t address,
-                                              span<uint_least8_t> data,
-                                              bool sendStop) {
-  return master->readPacket(address, data, sendStop);
-}
-
-} // namespace MaximInterface
--- a/Links/I2CMasterDecorator.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*******************************************************************************
-* 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 & master) : master(&master) {}
-
-public:
-  void setMaster(I2CMaster & master) { this->master = &master; }
-
-  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(span<const uint_least8_t> data);
-  
-  MaximInterface_EXPORT virtual error_code readByte(AckStatus status,
-                                                    uint_least8_t & data);
-  
-  MaximInterface_EXPORT virtual error_code
-  readBlock(AckStatus status, span<uint_least8_t> data);
-
-protected:
-  MaximInterface_EXPORT virtual error_code
-  writePacketImpl(uint_least8_t address, span<const uint_least8_t> data,
-                  bool sendStop);
-                  
-  MaximInterface_EXPORT virtual error_code
-  readPacketImpl(uint_least8_t address, span<uint_least8_t> data,
-                 bool sendStop);
-
-private:
-  I2CMaster * master;
-};
-
-} // namespace MaximInterface
-
-#endif
--- a/Links/LoggingI2CMaster.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*******************************************************************************
-* 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(span<const uint_least8_t> data, bool read) {
-  string dataBuilder;
-  for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) {
-    if (read) {
-      dataBuilder.append(1, '[');
-    }
-    dataBuilder.append(byteArrayToHexString(data.subspan(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(make_span(&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(make_span(&data, 1), false));
-  return I2CMasterDecorator::writeByte(data);
-}
-
-error_code LoggingI2CMaster::writeBlock(span<const uint_least8_t> data) {
-  messageBuilder.append(formatDataString(data, false));
-  return I2CMasterDecorator::writeBlock(data);
-}
-
-error_code LoggingI2CMaster::writePacketImpl(uint_least8_t address,
-                                             span<const uint_least8_t> data,
-                                             bool sendStop) {
-  messageBuilder.append(startString);
-  messageBuilder.append(formatDataString(make_span(&address, 1), false));
-  error_code result =
-      I2CMasterDecorator::writePacketImpl(address, data, sendStop);
-  if (!result) {
-    messageBuilder.append(formatDataString(data, 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(make_span(&data, 1), true));
-  }
-  return result;
-}
-
-error_code LoggingI2CMaster::readBlock(AckStatus status,
-                                       span<uint_least8_t> data) {
-  error_code result = I2CMasterDecorator::readBlock(status, data);
-  if (!result) {
-    messageBuilder.append(formatDataString(data, true));
-  }
-  return result;
-}
-
-error_code LoggingI2CMaster::readPacketImpl(uint_least8_t address,
-                                            span<uint_least8_t> data,
-                                            bool sendStop) {
-  messageBuilder.append(startString);
-  messageBuilder.append(formatDataString(make_span(&address, 1), false));
-  error_code result =
-      I2CMasterDecorator::readPacketImpl(address, data, sendStop);
-  if (!result) {
-    messageBuilder.append(formatDataString(data, true));
-  }
-  if (sendStop || result) {
-    messageBuilder.append(stopString);
-    tryWriteMessage();
-  }
-  return result;
-}
-
-} // namespace MaximInterface
--- a/Links/LoggingI2CMaster.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*******************************************************************************
-* 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(span<const uint_least8_t> data);
-  
-  MaximInterface_EXPORT virtual error_code readByte(AckStatus status,
-                                                    uint_least8_t & data);
-  MaximInterface_EXPORT virtual error_code
-  readBlock(AckStatus status, span<uint_least8_t> data);
-
-protected:
-  MaximInterface_EXPORT virtual error_code
-  writePacketImpl(uint_least8_t address, span<const uint_least8_t> data,
-                  bool sendStop);
-                  
-  MaximInterface_EXPORT virtual error_code
-  readPacketImpl(uint_least8_t address, span<uint_least8_t> data,
-                 bool sendStop);
-
-private:
-  void tryWriteMessage();
-
-  WriteMessage writeMessage;
-  std::string messageBuilder;
-};
-
-} // namespace MaximInterface
-
-#endif
--- a/Links/LoggingOneWireMaster.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-/*******************************************************************************
-* 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(span<const uint_least8_t> data, bool read) {
-  string dataBuilder;
-  for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) {
-    if (read) {
-      dataBuilder.append(1, '[');
-    }
-    dataBuilder.append(byteArrayToHexString(data.subspan(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(make_span(&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(make_span(&recvByte, 1), true));
-    if (afterLevel == StrongLevel) {
-      tryWriteMessage(strongLevelString);
-    }
-  }
-  return result;
-}
-
-error_code LoggingOneWireMaster::writeBlock(span<const uint_least8_t> sendBuf) {
-  tryWriteMessage(formatDataString(sendBuf, false));
-  return OneWireMasterDecorator::writeBlock(sendBuf);
-}
-
-error_code LoggingOneWireMaster::readBlock(span<uint_least8_t> recvBuf) {
-  error_code result = OneWireMasterDecorator::readBlock(recvBuf);
-  if (!result) {
-    tryWriteMessage(formatDataString(recvBuf, 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
--- a/Links/LoggingOneWireMaster.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*******************************************************************************
-* 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(span<const uint_least8_t> sendBuf);
-  
-  MaximInterface_EXPORT virtual error_code
-  readBlock(span<uint_least8_t> recvBuf);
-  
-  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
--- a/Links/LoggingSleep.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*******************************************************************************
-* 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::invoke(int ms) const {
-  if (writeMessage) {
-    std::ostringstream message;
-    message << "<DELAY" << ms << '>';
-    writeMessage(message.str());
-  }
-  SleepDecorator::invoke(ms);
-}
-
-} // namespace MaximInterface
--- a/Links/LoggingSleep.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*******************************************************************************
-* 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(Sleep & sleep,
-               const WriteMessage & writeMessage = WriteMessage())
-      : SleepDecorator(sleep), writeMessage(writeMessage) {}
-
-  void setWriteMessage(const WriteMessage & writeMessage) {
-    this->writeMessage = writeMessage;
-  }
-
-  MaximInterface_EXPORT virtual void invoke(int ms) const;
-
-private:
-  WriteMessage writeMessage;
-};
-
-} // namespace MaximInterface
-
-#endif
--- a/Links/OneWireMaster.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*******************************************************************************
-* 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 {
-
-static const int maxBitNum = 7;
-
-error_code OneWireMaster::writeByteSetLevel(uint_least8_t sendByte,
-                                            Level afterLevel) {
-  error_code result;
-  for (int bitNum = 0; (bitNum <= maxBitNum) && !result; ++bitNum) {
-    result = writeBitSetLevel(((sendByte >> bitNum) & 1) == 1,
-                              (bitNum == maxBitNum) ? afterLevel : NormalLevel);
-  }
-  return result;
-}
-
-error_code OneWireMaster::readByteSetLevel(uint_least8_t & recvByte,
-                                           Level afterLevel) {
-  recvByte = 0;
-  error_code result;
-  for (int bitNum = 0; bitNum <= maxBitNum; ++bitNum) {
-    bool recvBit;
-    result = readBitSetLevel(recvBit,
-                             (bitNum == maxBitNum) ? afterLevel : NormalLevel);
-    if (result) {
-      break;
-    }
-    if (recvBit) {
-      recvByte |= (1 << bitNum);
-    }
-  }
-  return result;
-}
-
-error_code OneWireMaster::writeBlock(span<const uint_least8_t> sendBuf) {
-  error_code result;
-  for (span<const uint_least8_t>::index_type i = 0;
-       i < sendBuf.size() && !result; ++i) {
-    result = writeByte(sendBuf[i]);
-  }
-  return result;
-}
-
-error_code OneWireMaster::readBlock(span<uint_least8_t> recvBuf) {
-  error_code result;
-  for (span<uint_least8_t>::index_type i = 0; i < recvBuf.size() && !result;
-       ++i) {
-    result = readByte(recvBuf[i]);
-  }
-  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
--- a/Links/OneWireMaster.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +0,0 @@
-/*******************************************************************************
-* 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 <stdint.h>
-#include <MaximInterface/Utilities/Export.h>
-#include <MaximInterface/Utilities/span.hpp>
-#include <MaximInterface/Utilities/system_error.hpp>
-
-namespace MaximInterface {
-
-/// 1-Wire master interface.
-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() {}
-
-  /// @brief
-  /// 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;
-
-  /// @brief
-  /// 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;
-
-  /// @brief
-  /// 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);
-
-  /// @brief
-  /// 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);
-
-  /// @brief Send a block of communication on the 1-Wire bus.
-  /// @param[in] sendBuf Buffer to send on the 1-Wire bus.
-  MaximInterface_EXPORT virtual error_code
-  writeBlock(span<const uint_least8_t> sendBuf);
-
-  /// @brief Receive a block of communication on the 1-Wire bus.
-  /// @param[out] recvBuf Buffer to receive the data from the 1-Wire bus.
-  MaximInterface_EXPORT virtual error_code
-  readBlock(span<uint_least8_t> recvBuf);
-
-  /// 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;
-
-  /// @brief 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);
-
-  /// @brief
-  /// 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);
-  }
-
-  /// @brief
-  /// 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 touchBit(bool & sendRecvBit) {
-    return touchBitSetLevel(sendRecvBit, NormalLevel);
-  }
-  
-  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
--- a/Links/OneWireMasterDecorator.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*******************************************************************************
-* 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(span<const uint_least8_t> sendBuf) {
-  return master->writeBlock(sendBuf);
-}
-
-error_code OneWireMasterDecorator::readBlock(span<uint_least8_t> recvBuf) {
-  return master->readBlock(recvBuf);
-}
-
-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
--- a/Links/OneWireMasterDecorator.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*******************************************************************************
-* 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 setMaster(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(span<const uint_least8_t> sendBuf);
-  
-  MaximInterface_EXPORT virtual error_code
-  readBlock(span<uint_least8_t> recvBuf);
-  
-  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
--- a/Links/RomCommands.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,210 +0,0 @@
-/*******************************************************************************
-* 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 "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, RomId::const_span romId) {
-  SearchRomState searchState(romId);
-  error_code result = searchRom(master, searchState);
-  if (result) {
-    return result;
-  }
-  // Check if same device found.
-  if (romId != make_span(searchState.romId)) {
-    result = make_error_code(OneWireMaster::NoSlaveError);
-  }
-  return result;
-}
-
-error_code readRom(OneWireMaster & master, RomId::span romId) {
-  error_code result = master.reset();
-  if (result) {
-    return result;
-  }
-  result = master.writeByte(ReadRomCmd);
-  if (result) {
-    return result;
-  }
-  result = master.readBlock(romId);
-  if (result) {
-    return result;
-  }
-  if (!valid(romId)) {
-    result = make_error_code(OneWireMaster::NoSlaveError);
-  }
-  return result;
-}
-
-error_code skipRom(OneWireMaster & master) {
-  error_code result = master.reset();
-  if (result) {
-    return result;
-  }
-  result = master.writeByte(SkipRomCmd);
-  return result;
-}
-
-error_code matchRom(OneWireMaster & master, RomId::const_span romId) {
-  error_code result = master.reset();
-  if (result) {
-    return result;
-  }
-  result = master.writeByte(MatchRomCmd);
-  if (result) {
-    return result;
-  }
-  result = master.writeBlock(romId);
-  return result;
-}
-
-error_code overdriveSkipRom(OneWireMaster & master) {
-  error_code result = master.reset();
-  if (result) {
-    return result;
-  }
-  result = master.writeByte(OverdriveSkipRomCmd);
-  if (result) {
-    return result;
-  }
-  result = master.setSpeed(OneWireMaster::OverdriveSpeed);
-  return result;
-}
-
-error_code overdriveMatchRom(OneWireMaster & master, RomId::const_span romId) {
-  error_code result = master.reset();
-  if (result) {
-    return result;
-  }
-  result = master.writeByte(OverdriveMatchRomCmd);
-  if (result) {
-    return result;
-  }
-  result = master.setSpeed(OneWireMaster::OverdriveSpeed);
-  if (result) {
-    return result;
-  }
-  result = master.writeBlock(romId);
-  return result;
-}
-
-error_code resumeRom(OneWireMaster & master) {
-  error_code result = master.reset();
-  if (result) {
-    return 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;
-  newSearchState.lastFamilyDiscrepancy = searchState.lastFamilyDiscrepancy;
-  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 == searchState.lastDiscrepancy) {
-      tripletData.writeBit = 1;
-    } else if (idBitNumber > searchState.lastDiscrepancy) {
-      tripletData.writeBit = 0;
-    } else { // idBitNumber < searchState.lastDiscrepancy
-      tripletData.writeBit =
-          (searchState.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 if (!tripletData.readBit && !tripletData.readBitComplement) {
-      newSearchState.lastDiscrepancy = idBitNumber;
-      if (idBitNumber <= 8) {
-        newSearchState.lastFamilyDiscrepancy = idBitNumber;
-      }
-    }
-  }
-
-  if (valid(newSearchState.romId)) {
-    if (newSearchState.lastDiscrepancy == 0) {
-      newSearchState.lastDevice = true;
-    }
-    searchState = newSearchState;
-  } else {
-    result = make_error_code(OneWireMaster::NoSlaveError);
-  }
-  return result;
-}
-
-} // namespace MaximInterface
--- a/Links/RomCommands.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*******************************************************************************
-* 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
-/// @brief 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::array romId;
-  int_least8_t lastDiscrepancy;
-  int_least8_t lastFamilyDiscrepancy;
-  bool lastDevice;
-
-  SearchRomState()
-      : romId(), lastDiscrepancy(0), lastFamilyDiscrepancy(0),
-        lastDevice(false) {}
-    
-  explicit SearchRomState(RomId::const_span romId)
-      : lastDiscrepancy(64), lastFamilyDiscrepancy(0), lastDevice(false) {
-    copy(romId, make_span(this->romId));
-  }
-      
-  explicit SearchRomState(RomId::element familyCode)
-      : romId(), lastDiscrepancy(64), lastFamilyDiscrepancy(0),
-        lastDevice(false) {
-    setFamilyCode(romId, familyCode);
-  }
-};
-
-/// @brief
-/// 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,
-                                           RomId::const_span romId);
-
-/// @brief 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 there is more than one device on the bus.
-/// @param master 1-Wire master for operation.
-/// @param[out] romId ROM ID read from device.
-MaximInterface_EXPORT error_code readRom(OneWireMaster & master,
-                                         RomId::span romId);
-
-/// @brief Issue Skip ROM command on bus.
-/// @note
-/// Only use this command with a single-drop bus.
-/// Data collisions will occur if there is more than one device on the bus.
-MaximInterface_EXPORT error_code skipRom(OneWireMaster & master);
-
-/// @brief 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 master 1-Wire master for operation.
-/// @param[in] romId ROM ID of device to select.
-MaximInterface_EXPORT error_code matchRom(OneWireMaster & master,
-                                          RomId::const_span romId);
-
-/// @brief 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 there is more than one device on the bus.
-MaximInterface_EXPORT error_code overdriveSkipRom(OneWireMaster & master);
-
-/// @brief
-/// Use the Overdrive Match ROM command to select the device by its known ID.
-/// @param master 1-Wire master for operation.
-/// @param[in] romId ROM ID of device to select.
-MaximInterface_EXPORT error_code overdriveMatchRom(OneWireMaster & master,
-                                                   RomId::const_span romId);
-
-/// @brief Perform a Resume ROM command on bus.
-/// @details
-/// Resumes communication with the last device selected through a Match ROM or
-/// Search ROM operation.
-MaximInterface_EXPORT error_code resumeRom(OneWireMaster & master);
-
-/// @brief 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
--- a/Links/RunCommand.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,210 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2018 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/crc.hpp>
-#include <MaximInterface/Utilities/Error.hpp>
-#include "I2CMaster.hpp"
-#include "OneWireMaster.hpp"
-#include "Sleep.hpp"
-#include "RunCommand.hpp"
-
-namespace MaximInterface {
-
-const error_category & RunCommandWithOneWireMaster::errorCategory() {
-  static class : public error_category {
-  public:
-    virtual const char * name() const { return "RunCommandWithOneWireMaster"; }
-
-    virtual std::string message(int condition) const {
-      switch (condition) {
-      case CrcError:
-        return "CRC Error";
-
-      case InvalidResponseError:
-        return "Invalid Response Error";
-      }
-      return defaultErrorMessage(condition);
-    }
-  } instance;
-  return instance;
-}
-
-error_code RunCommandWithOneWireMaster::
-operator()(span<const uint_least8_t> command, int delayTime,
-           span<uint_least8_t> & response) const {
-  // Write command.
-  error_code result = selectRom(*master);
-  if (result) {
-    return result;
-  }
-  uint_least8_t xpcBuffer[2] = {0x66,
-                                static_cast<uint_least8_t>(command.size())};
-  result = master->writeBlock(xpcBuffer);
-  if (result) {
-    return result;
-  }
-  result = master->writeBlock(command);
-  if (result) {
-    return result;
-  }
-  uint_fast16_t expectedCrc =
-      calculateCrc16(command, calculateCrc16(xpcBuffer)) ^ 0xFFFFU;
-  result = master->readBlock(xpcBuffer);
-  if (result) {
-    return result;
-  }
-  if (expectedCrc !=
-      ((static_cast<uint_fast16_t>(xpcBuffer[1]) << 8) | xpcBuffer[0])) {
-    return make_error_code(CrcError);
-  }
-  result = master->writeBytePower(0xAA);
-  if (result) {
-    return result;
-  }
-
-  // Wait for device to process.
-  sleep->invoke(delayTime);
-
-  // Read response.
-  result = master->setLevel(OneWireMaster::NormalLevel);
-  if (result) {
-    return result;
-  }
-  result = master->readBlock(xpcBuffer);
-  if (result) {
-    return result;
-  }
-  if (xpcBuffer[1] > response.size()) {
-    return make_error_code(InvalidResponseError);
-  }
-  response = response.first(xpcBuffer[1]);
-  result = master->readBlock(response);
-  if (result) {
-    return result;
-  }
-  expectedCrc =
-      calculateCrc16(response, calculateCrc16(make_span(xpcBuffer + 1, 1))) ^
-      0xFFFFU;
-  result = master->readBlock(xpcBuffer);
-  if (result) {
-    return result;
-  }
-  if (expectedCrc !=
-      ((static_cast<uint_fast16_t>(xpcBuffer[1]) << 8) | xpcBuffer[0])) {
-    return make_error_code(CrcError);
-  }
-  return result;
-}
-
-const error_category & RunCommandWithI2CMaster::errorCategory() {
-  static class : public error_category {
-  public:
-    virtual const char * name() const { return "RunCommandWithI2CMaster"; }
-
-    virtual std::string message(int condition) const {
-      switch (condition) {
-      case InvalidResponseError:
-        return "Invalid Response Error";
-      }
-      return defaultErrorMessage(condition);
-    }
-  } instance;
-  return instance;
-}
-
-error_code RunCommandWithI2CMaster::
-operator()(span<const uint_least8_t> command, int delayTime,
-           span<uint_least8_t> & response) const {
-  // Write command.
-  error_code result = master->start(address_);
-  if (result == make_error_condition(I2CMaster::NackError) && address_ != 0) {
-    result = master->start(0);
-  }
-  if (result) {
-    master->stop();
-    return result;
-  }
-  if (!command.empty()) {
-    result = master->writeByte(command[0]);
-    if (result) {
-      master->stop();
-      return result;
-    }
-    command = command.subspan(1);
-    if (!command.empty()) {
-      result = master->writeByte(command.size());
-      if (result) {
-        master->stop();
-        return result;
-      }
-      result = master->writeBlock(command);
-      if (result) {
-        master->stop();
-        return result;
-      }
-    }
-  }
-  result = master->stop();
-  if (result) {
-    return result;
-  }
-
-  // Wait for device to process.
-  sleep->invoke(delayTime);
-
-  // Read response.
-  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;
-  }
-  if (length > response.size()) {
-    master->stop();
-    return make_error_code(InvalidResponseError);
-  }
-  response = response.first(length);
-  result = master->readBlock(I2CMaster::Nack, response);
-  if (result) {
-    master->stop();
-    return result;
-  }
-  result = master->stop();
-  return result;
-}
-
-} // namespace MaximInterface
--- a/Links/RunCommand.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2018 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_RunCommand
-#define MaximInterface_RunCommand
-
-#include <MaximInterface/Utilities/Export.h>
-#include <MaximInterface/Utilities/Function.hpp>
-#include <MaximInterface/Utilities/span.hpp>
-#include <MaximInterface/Utilities/system_error.hpp>
-#include "SelectRom.hpp"
-
-namespace MaximInterface {
-
-class I2CMaster;
-class OneWireMaster;
-class Sleep;
-
-typedef Function<error_code(span<const uint_least8_t>, int,
-                            span<uint_least8_t> &)>
-    RunCommand;
-
-class RunCommandWithOneWireMaster {
-public:
-  typedef RunCommand::result_type result_type;
-
-  enum ErrorValue { CrcError = 1, InvalidResponseError };
-  MaximInterface_EXPORT static const error_category & errorCategory();
-
-  RunCommandWithOneWireMaster(Sleep & sleep, OneWireMaster & master,
-                              const SelectRom & selectRom)
-      : selectRom(selectRom), master(&master), sleep(&sleep) {}
-
-  void setSleep(Sleep & sleep) { this->sleep = &sleep; }
-  
-  void setMaster(OneWireMaster & master) { this->master = &master; }
-  
-  void setSelectRom(const SelectRom & selectRom) {
-    this->selectRom = selectRom;
-  }
-
-  MaximInterface_EXPORT error_code
-  operator()(span<const uint_least8_t> command, int delayTime,
-             span<uint_least8_t> & response) const;
-
-private:
-  SelectRom selectRom;
-  OneWireMaster * master;
-  const Sleep * sleep;
-};
-
-inline error_code make_error_code(RunCommandWithOneWireMaster::ErrorValue e) {
-  return error_code(e, RunCommandWithOneWireMaster::errorCategory());
-}
-
-class RunCommandWithI2CMaster {
-public:
-  typedef RunCommand::result_type result_type;
-
-  enum ErrorValue { InvalidResponseError = 1 };
-  MaximInterface_EXPORT static const error_category & errorCategory();
-
-  RunCommandWithI2CMaster(Sleep & sleep, I2CMaster & master,
-                          uint_least8_t address)
-      : sleep(&sleep), master(&master), address_(address & 0xFE) {}
-
-  void setSleep(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) { address_ = address & 0xFE; }
-
-  MaximInterface_EXPORT error_code
-  operator()(span<const uint_least8_t> command, int delayTime,
-             span<uint_least8_t> & response) const;
-
-private:
-  const Sleep * sleep;
-  I2CMaster * master;
-  uint_least8_t address_;
-};
-
-inline error_code make_error_code(RunCommandWithI2CMaster::ErrorValue e) {
-  return error_code(e, RunCommandWithI2CMaster::errorCategory());
-}
-
-} // namespace MaximInterface
-
-#endif
--- a/Links/SelectRom.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*******************************************************************************
-* 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->lastRomId) {
-    result = resumeRom(master);
-  } else {
-    result = matchRom(master, romId_);
-    data->lastRomId = romId_;
-  }
-  return result;
-}
-
-} // namespace MaximInterface
--- a/Links/SelectRom.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*******************************************************************************
-* 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;
-
-/// Selects a 1-Wire device on the bus for communication.
-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(RomId::const_span romId) { setRomId(romId); }
-
-  RomId::const_span romId() const { return romId_; }
-  
-  void setRomId(RomId::const_span romId) { copy(romId, make_span(romId_)); }
-
-  MaximInterface_EXPORT error_code operator()(OneWireMaster & master) const;
-
-private:
-  RomId::array romId_;
-};
-
-/// @brief
-/// 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 {
-    SharedData() : lastRomId() {}
-    RomId::array lastRomId;
-  };
-
-  SelectMatchRomWithResume(SharedData & data, RomId::const_span romId)
-      : data(&data) {
-    setRomId(romId);
-  }
-
-  void setSharedData(SharedData & data) { this->data = &data; }
-  
-  RomId::const_span romId() const { return romId_; }
-  
-  void setRomId(RomId::const_span romId) { copy(romId, make_span(romId_)); }
-
-  MaximInterface_EXPORT error_code operator()(OneWireMaster & master) const;
-
-private:
-  SharedData * data;
-  RomId::array romId_;
-};
-
-} // namespace MaximInterface
-
-#endif
--- a/Links/SerialPort.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*******************************************************************************
-* 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_SerialPort
-#define MaximInterface_SerialPort
-
-#include <string>
-#include "Uart.hpp"
-
-namespace MaximInterface {
-
-class SerialPort : public Uart {
-public:
-  /// Connect a specified COM port.
-  virtual error_code connect(const std::string & portName) = 0;
-  
-  /// Disconnect from the current port.
-  virtual error_code disconnect() = 0;
-  
-  /// @brief Check if currently connected to a port.
-  /// @returns True if connected.
-  virtual bool connected() const = 0;
-
-  /// Get the currently connected port name.
-  virtual std::string portName() const = 0;
-};
-
-}
-
-#endif
--- a/Links/Sleep.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*******************************************************************************
-* 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 invoke(int ms) const = 0;
-  void operator()(int ms) const { invoke(ms); }
-};
-
-} // namespace MaximInterface
-
-#endif
--- a/Links/SleepDecorator.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*******************************************************************************
-* 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::invoke(int ms) const { sleep->invoke(ms); }
-
-}
--- a/Links/SleepDecorator.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*******************************************************************************
-* 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(Sleep & sleep) : sleep(&sleep) {}
-
-public:
-  void setSleep(Sleep & sleep) { this->sleep = &sleep; }
-  MaximInterface_EXPORT virtual void invoke(int ms) const;
-
-private:
-  const Sleep * sleep;
-};
-
-} // namespace MaximInterface
-
-#endif
--- a/Links/Uart.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*******************************************************************************
-* 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(span<const uint_least8_t> data) {
-  error_code result;
-  for (span<const uint_least8_t>::index_type i = 0;
-       i < data.size() && !result; ++i) {
-    result = writeByte(data[i]);
-  }
-  return result;
-}
-
-error_code Uart::readBlock(span<uint_least8_t> data) {
-  error_code result;
-  for (span<uint_least8_t>::index_type i = 0; i < data.size() && !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
--- a/Links/Uart.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*******************************************************************************
-* 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 <MaximInterface/Utilities/Export.h>
-#include <MaximInterface/Utilities/span.hpp>
-#include <MaximInterface/Utilities/system_error.hpp>
-
-namespace MaximInterface {
-
-/// Universal asynchronous receiver-transmitter interface.
-class Uart {
-public:
-  enum ErrorValue {
-    TimeoutError = 1, ///< Read operation aborted due to timeout.
-    OverrunError      ///< Received data lost due to read buffer overrun.
-  };
-
-  virtual ~Uart() {}
-
-  /// Set the baud rate of the port in Hz.
-  virtual error_code setBaudRate(int_least32_t baudRate) = 0;
-  
-  /// Generate a break condition on the port for a small amount of time.
-  virtual error_code sendBreak() = 0;
-  
-  /// Clear all received data that was buffered.
-  virtual error_code clearReadBuffer() = 0;
-  
-  /// Writes a byte of data to the port.
-  virtual error_code writeByte(uint_least8_t data) = 0;
-  
-  /// Writes a block of data to the port.
-  MaximInterface_EXPORT virtual error_code
-  writeBlock(span<const uint_least8_t> data);
-  
-  /// @brief
-  /// Reads a byte of data from the port. Block until data is received or a
-  /// timeout is reached.
-  /// @param[out] data Data read from the port if successful.
-  virtual error_code readByte(uint_least8_t & data) = 0;
-  
-  /// @brief
-  /// Read a block of data from the port. Block until data is received or a
-  /// timeout is reached.
-  /// @param[out] data Data read from the port if successful.
-  MaximInterface_EXPORT virtual error_code readBlock(span<uint_least8_t> data);
-
-  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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/Algorithm.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,64 @@
+/*******************************************************************************
+* Copyright (C) 2018 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 MaximInterfaceCore_Algorithm
+#define MaximInterfaceCore_Algorithm
+
+#include <algorithm>
+#include "span.hpp"
+#include "type_traits.hpp"
+
+/// Alternative to std::max when a constant expression is required.
+#define MaximInterfaceCore_MAX(a, b) ((a) < (b) ? (b) : (a))
+
+/// Alternative to std::min when a constant expression is required.
+#define MaximInterfaceCore_MIN(a, b) ((b) < (a) ? (b) : (a))
+
+namespace MaximInterfaceCore {
+
+/// Deep copy between static extent spans of the same size.
+template <typename T, size_t Extent, typename U>
+typename enable_if<Extent != dynamic_extent>::type copy(span<T, Extent> src,
+                                                        span<U, Extent> dst) {
+  std::copy(src.begin(), src.end(), dst.begin());
+}
+
+/// Deep equality between static extent spans of the same size.
+template <typename T, size_t Extent, typename U>
+typename enable_if<Extent != dynamic_extent, bool>::type
+equal(span<T, Extent> lhs, span<U, Extent> rhs) {
+  return std::equal(lhs.begin(), lhs.end(), rhs.begin());
+}
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/ChangeSizeType.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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.
+*******************************************************************************/
+
+#ifndef MaximInterfaceCore_ChangeSizeType
+#define MaximInterfaceCore_ChangeSizeType
+
+#include <stdint.h>
+#include <algorithm>
+#include <limits>
+#include "span.hpp"
+#include "system_error.hpp"
+
+namespace MaximInterfaceCore {
+
+/// @brief
+/// Adapts functions taking an array pointer and size where the size type is
+/// nonstandard.
+/// @tparam NewSize Nonstandard size type.
+/// @tparam Func Must be callable as func(Data *, NewSize).
+/// @tparam Data Array element type.
+/// @param func Callback for processing chunks of data.
+/// @param data Data to process with callback.
+template <typename NewSize, typename Func, typename Data>
+error_code changeSizeType(Func func, span<Data> data) {
+  typedef typename span<Data>::index_type DataSize;
+
+  error_code result;
+  // Check if NewSize can represent the maximum value of DataSize.
+  if (static_cast<uintmax_t>(std::numeric_limits<DataSize>::max()) >
+      static_cast<uintmax_t>(std::numeric_limits<NewSize>::max())) {
+    DataSize dataIdx = 0;
+    do {
+      const span<Data> chunk = data.subspan(
+          dataIdx, std::min<DataSize>(data.size() - dataIdx,
+                                      std::numeric_limits<NewSize>::max()));
+      result = func(chunk.data(), static_cast<NewSize>(chunk.size()));
+      dataIdx += chunk.size();
+    } while (dataIdx < data.size() && !result);
+  } else {
+    result = func(data.data(), static_cast<NewSize>(data.size()));
+  }
+  return result;
+}
+
+} // namespace MaximInterfaceCore
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/Config.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,35 @@
+/*******************************************************************************
+* 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 MaximInterfaceCore_EXPORT
+  #define MaximInterfaceCore_EXPORT
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/Ecc256.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 "Ecc256.hpp"
+
+namespace MaximInterfaceCore {
+namespace Ecc256 {
+
+void copy(Point::const_span src, Point::span dst) {
+  copy(src.x, dst.x);
+  copy(src.y, dst.y);
+}
+
+void copy(KeyPair::const_span src, KeyPair::span dst) {
+  copy(src.privateKey, dst.privateKey);
+  copy(src.publicKey, dst.publicKey);
+}
+
+void copy(Signature::const_span src, Signature::span dst) {
+  copy(src.r, dst.r);
+  copy(src.s, dst.s);
+}
+
+PublicKey::span CertificateData::publicKey() {
+  const PublicKey::span span = {
+      make_span(result_).subspan<publicKeyIdx, Scalar::size>(),
+      make_span(result_).subspan<publicKeyIdx + Scalar::size, Scalar::size>()};
+  return span;
+}
+
+} // namespace Ecc256
+} // namespace MaximInterfaceCore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/Ecc256.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,244 @@
+/*******************************************************************************
+* 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 MaximInterfaceCore_Ecc256
+#define MaximInterfaceCore_Ecc256
+
+#include <stdint.h>
+#include "Algorithm.hpp"
+#include "array_span.hpp"
+#include "Config.hpp"
+#include "ManId.hpp"
+#include "RomId.hpp"
+#include "Unconstructible.hpp"
+
+namespace MaximInterfaceCore {
+namespace Ecc256 {
+
+typedef array_span<uint_least8_t, 32> Scalar;
+
+struct Point : Unconstructible {
+  struct const_span {
+    Scalar::const_span x;
+    Scalar::const_span y;
+  };
+
+  struct span {
+    Scalar::span x;
+    Scalar::span y;
+
+    operator const_span() const {
+      const const_span sp = {x, y};
+      return sp;
+    }
+  };
+
+  struct array {
+    Scalar::array x;
+    Scalar::array y;
+
+    operator span() {
+      const span sp = {x, y};
+      return sp;
+    }
+
+    operator const_span() const {
+      const const_span sp = {x, y};
+      return sp;
+    }
+  };
+};
+
+MaximInterfaceCore_EXPORT void copy(Point::const_span src, Point::span dst);
+
+typedef Scalar PrivateKey;
+typedef Point PublicKey;
+
+struct KeyPair : Unconstructible {
+  struct const_span {
+    PrivateKey::const_span privateKey;
+    PublicKey::const_span publicKey;
+  };
+
+  struct span {
+    PrivateKey::span privateKey;
+    PublicKey::span publicKey;
+
+    operator const_span() const {
+      const const_span sp = {privateKey, publicKey};
+      return sp;
+    }
+  };
+
+  struct array {
+    PrivateKey::array privateKey;
+    PublicKey::array publicKey;
+
+    operator span() {
+      const span sp = {privateKey, publicKey};
+      return sp;
+    }
+
+    operator const_span() const {
+      const const_span sp = {privateKey, publicKey};
+      return sp;
+    }
+  };
+};
+
+MaximInterfaceCore_EXPORT void copy(KeyPair::const_span src, KeyPair::span dst);
+
+struct Signature : Unconstructible {
+  struct const_span {
+    Scalar::const_span r;
+    Scalar::const_span s;
+  };
+
+  struct span {
+    Scalar::span r;
+    Scalar::span s;
+
+    operator const_span() const {
+      const const_span sp = {r, s};
+      return sp;
+    }
+  };
+
+  struct array {
+    Scalar::array r;
+    Scalar::array s;
+
+    operator span() {
+      const span sp = {r, s};
+      return sp;
+    }
+
+    operator const_span() const {
+      const const_span sp = {r, s};
+      return sp;
+    }
+  };
+};
+
+MaximInterfaceCore_EXPORT void copy(Signature::const_span src,
+                                    Signature::span dst);
+
+/// Data used to create a device key certificate for ECC-256 authenticators.
+class CertificateData {
+public:
+  typedef array_span<uint_least8_t,
+                     2 * Scalar::size + RomId::size + ManId::size>
+      Result;
+
+  CertificateData() : result_() {}
+
+  /// Formatted data result.
+  Result::const_span result() const { return result_; }
+
+  /// @name Public Key
+  /// @brief Public key of the device.
+  /// @{
+
+  /// Get mutable Public Key.
+  MaximInterfaceCore_EXPORT PublicKey::span publicKey();
+
+  /// Get immutable Public Key.
+  PublicKey::const_span publicKey() const {
+    return const_cast<CertificateData &>(*this).publicKey();
+  }
+
+  /// Set Public Key.
+  CertificateData & setPublicKey(PublicKey::const_span publicKey) {
+    copy(publicKey, this->publicKey());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  RomId::span romId() {
+    return make_span(result_).subspan<romIdIdx, RomId::size>();
+  }
+
+  /// Get immutable ROM ID.
+  RomId::const_span romId() const {
+    return const_cast<CertificateData &>(*this).romId();
+  }
+
+  /// Set ROM ID.
+  CertificateData & setRomId(RomId::const_span romId) {
+    copy(romId, this->romId());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  ManId::span manId() {
+    return make_span(result_).subspan<manIdIdx, ManId::size>();
+  }
+
+  /// Get immutable MAN ID.
+  ManId::const_span manId() const {
+    return const_cast<CertificateData &>(*this).manId();
+  }
+
+  /// Set MAN ID.
+  CertificateData & setManId(ManId::const_span manId) {
+    copy(manId, this->manId());
+    return *this;
+  }
+
+  /// @}
+
+private:
+  typedef Result::span::index_type index;
+
+  static const index publicKeyIdx = 0;
+  static const index romIdIdx = publicKeyIdx + 2 * Scalar::size;
+  static const index manIdIdx = romIdIdx + RomId::size;
+
+  Result::array result_;
+};
+
+} // namespace Ecc256
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/Error.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 MaximInterfaceCore {
+
+const char * defaultErrorMessage(int condition) {
+  return (condition == 0) ? "Success" : "Unknown Error";
+}
+
+} // namespace MaximInterfaceCore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/Error.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 MaximInterfaceCore_Error
+#define MaximInterfaceCore_Error
+
+#include "Config.hpp"
+
+namespace MaximInterfaceCore {
+
+/// @brief Get the default error message associated with a condition.
+/// @details Typically used by an error_category when the condition is unknown.
+MaximInterfaceCore_EXPORT const char * defaultErrorMessage(int condition);
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/FlagSet.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,226 @@
+/*******************************************************************************
+* 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 MaximInterfaceCore_FlagSet
+#define MaximInterfaceCore_FlagSet
+
+#include <stddef.h>
+#include <bitset>
+
+namespace MaximInterfaceCore {
+
+/// @brief
+/// 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 bits != rhs.bits; }
+
+  /// @name 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(); }
+
+  /// @}
+
+  /// @name Capacity
+  /// @{
+
+  size_t size() const { return bits.size(); }
+
+  /// @}
+
+  /// @name 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;
+  }
+
+  /// @}
+
+  /// @name 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 MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/Function.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,565 @@
+/*******************************************************************************
+* 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 MaximInterfaceCore_Function
+#define MaximInterfaceCore_Function
+
+#include <stddef.h>
+#include "SafeBool.hpp"
+#include "type_traits.hpp"
+
+// Include for std::swap.
+#include <algorithm>
+#include <utility>
+
+namespace MaximInterfaceCore {
+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 aligner1;
+  long int aligner2;
+  void * aligner3;
+};
+
+// 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-3 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 SafeBool() const {
+    return makeSafeBool(callableWrapper.target() != NULL);
+  }
+
+  ResultType operator()() const {
+    return callableWrapper.target() ? callableWrapper.target()->invoke()
+                                    : ResultType();
+  }
+
+private:
+  class Callable {
+  public:
+    virtual ~Callable() {}
+    virtual ResultType invoke() 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 invoke() 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 SafeBool() const {
+    return makeSafeBool(callableWrapper.target() != NULL);
+  }
+
+  ResultType operator()(ArgumentType arg) const {
+    return callableWrapper.target() ? callableWrapper.target()->invoke(arg)
+                                    : ResultType();
+  }
+
+private:
+  class Callable {
+  public:
+    virtual ~Callable() {}
+    virtual ResultType invoke(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 invoke(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 SafeBool() const {
+    return makeSafeBool(callableWrapper.target() != NULL);
+  }
+
+  ResultType operator()(FirstArgumentType arg1, SecondArgumentType arg2) const {
+    return callableWrapper.target()
+               ? callableWrapper.target()->invoke(arg1, arg2)
+               : ResultType();
+  }
+
+private:
+  class Callable {
+  public:
+    virtual ~Callable() {}
+    virtual ResultType invoke(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 invoke(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);
+}
+
+// Function implementation for three argument functions.
+template <typename FirstArgumentType, typename SecondArgumentType,
+          typename ThirdArgumentType, typename ResultType>
+class Function<ResultType(FirstArgumentType, SecondArgumentType,
+                          ThirdArgumentType)> {
+public:
+  typedef ResultType result_type;
+
+  Function(ResultType (*func)(FirstArgumentType, SecondArgumentType,
+                              ThirdArgumentType) = NULL)
+      : callableWrapper() {
+    if (func) {
+      callableWrapper = func;
+    }
+  }
+
+  template <typename F> Function(F func) : callableWrapper(func) {}
+
+  const Function & operator=(ResultType (*func)(FirstArgumentType,
+                                                SecondArgumentType,
+                                                ThirdArgumentType)) {
+    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 SafeBool() const {
+    return makeSafeBool(callableWrapper.target() != NULL);
+  }
+
+  ResultType operator()(FirstArgumentType arg1, SecondArgumentType arg2,
+                        ThirdArgumentType arg3) const {
+    return callableWrapper.target()
+               ? callableWrapper.target()->invoke(arg1, arg2, arg3)
+               : ResultType();
+  }
+
+private:
+  class Callable {
+  public:
+    virtual ~Callable() {}
+    virtual ResultType invoke(FirstArgumentType, SecondArgumentType,
+                              ThirdArgumentType) 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 invoke(FirstArgumentType arg1, SecondArgumentType arg2,
+                              ThirdArgumentType arg3) const {
+      return func(arg1, arg2, arg3);
+    }
+
+    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 ThirdArgumentType, typename ResultType>
+inline void swap(Function<ResultType(FirstArgumentType, SecondArgumentType,
+                                     ThirdArgumentType)> & lhs,
+                 Function<ResultType(FirstArgumentType, SecondArgumentType,
+                                     ThirdArgumentType)> & rhs) {
+  lhs.swap(rhs);
+}
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/HexConversions.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 <cctype>
+#include <cstdio>
+#include <cstdlib>
+#include "HexConversions.hpp"
+
+using std::string;
+using std::vector;
+
+namespace MaximInterfaceCore {
+
+static const int charsPerByte = 2;
+
+string byteArrayToHexString(span<const uint_least8_t> byteArray) {
+  string hexString;
+  hexString.reserve(byteArray.size() * charsPerByte);
+  for (span<const uint_least8_t>::index_type i = 0; i < byteArray.size(); ++i) {
+    char hexBuf[charsPerByte + 1];
+    std::sprintf(hexBuf, "%2.2X", byteArray[i] & 0xFF);
+    hexString.append(hexBuf, charsPerByte);
+  }
+  return hexString;
+}
+
+Optional<vector<uint_least8_t> >
+hexStringToByteArray(const string & hexString) {
+  Optional<vector<uint_least8_t> > byteArray = vector<uint_least8_t>();
+  byteArray->reserve(hexString.size() / charsPerByte);
+  char hexBuf[charsPerByte + 1];
+  char * const hexBufEnd = hexBuf + charsPerByte;
+  *hexBufEnd = '\0';
+  char * hexBufIt = hexBuf;
+  for (string::const_iterator hexStringIt = hexString.begin(),
+                              hexStringEnd = hexString.end();
+       hexStringIt != hexStringEnd; ++hexStringIt) {
+    if (!std::isspace(*hexStringIt)) {
+      *hexBufIt = *hexStringIt;
+      if (++hexBufIt == hexBufEnd) {
+        char * hexBufParseEnd;
+        byteArray->push_back(static_cast<uint_least8_t>(
+            std::strtoul(hexBuf, &hexBufParseEnd, 16)));
+        if (hexBufParseEnd != hexBufEnd) {
+          break;
+        }
+        hexBufIt = hexBuf;
+      }
+    }
+  }
+  if (hexBufIt != hexBuf) {
+    byteArray.reset();
+  }
+  return byteArray;
+}
+
+} // namespace MaximInterfaceCore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/HexConversions.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,56 @@
+/*******************************************************************************
+* 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 MaximInterfaceCore_HexConversions
+#define MaximInterfaceCore_HexConversions
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string>
+#include <vector>
+#include "Config.hpp"
+#include "Optional.hpp"
+#include "span.hpp"
+
+namespace MaximInterfaceCore {
+
+/// Convert a byte array to a hex string.
+MaximInterfaceCore_EXPORT std::string
+byteArrayToHexString(span<const uint_least8_t> byteArray);
+
+/// Convert a hex string to a byte array.
+MaximInterfaceCore_EXPORT Optional<std::vector<uint_least8_t> >
+hexStringToByteArray(const std::string & hexString);
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/I2CMaster.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 "Error.hpp"
+#include "I2CMaster.hpp"
+
+namespace MaximInterfaceCore {
+
+error_code I2CMaster::writeBlock(span<const uint_least8_t> data) {
+  error_code result;
+  for (span<const uint_least8_t>::index_type i = 0;
+       i < data.size() && !result; ++i) {
+    result = writeByte(data[i]);
+  }
+  return result;
+}
+
+error_code I2CMaster::doWritePacket(uint_least8_t address,
+                                    span<const uint_least8_t> data,
+                                    bool sendStop) {
+  error_code result = start(address & 0xFE);
+  if (!result) {
+    result = writeBlock(data);
+  }
+  if (sendStop) {
+    error_code stopResult = stop();
+    if (!result) {
+      result = stopResult;
+    }
+  }
+  return result;
+}
+
+error_code I2CMaster::readBlock(AckStatus status, span<uint_least8_t> data) {
+  error_code result;
+  for (span<uint_least8_t>::index_type i = 0; i < data.size() && !result; ++i) {
+    result = readByte(i == (data.size() - 1) ? status : Ack, data[i]);
+  }
+  return result;
+}
+
+error_code I2CMaster::doReadPacket(uint_least8_t address,
+                                   span<uint_least8_t> data, bool sendStop) {
+  error_code result = start(address | 0x01);
+  if (!result) {
+    result = readBlock(Nack, data);
+  }
+  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 MaximInterfaceCore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/I2CMaster.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,124 @@
+/*******************************************************************************
+* 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 MaximInterfaceCore_I2CMaster
+#define MaximInterfaceCore_I2CMaster
+
+#include <stdint.h>
+#include "Config.hpp"
+#include "span.hpp"
+#include "system_error.hpp"
+
+namespace MaximInterfaceCore {
+
+/// I2C master interface.
+class I2CMaster {
+public:
+  enum ErrorValue {
+    NackError = 1 ///< Transaction stopped due to a NACK from the slave device.
+  };
+
+  enum AckStatus { Nack, Ack };
+
+  virtual ~I2CMaster() {}
+
+  /// @brief Send start condition and address on the bus.
+  /// @param address Address with R/W bit.
+  virtual error_code start(uint_least8_t address) = 0;
+
+  /// Send stop condition on the bus.
+  virtual error_code stop() = 0;
+
+  /// Write data byte to the bus.
+  virtual error_code writeByte(uint_least8_t data) = 0;
+
+  /// Write data block to the bus.
+  MaximInterfaceCore_EXPORT virtual error_code
+  writeBlock(span<const uint_least8_t> data);
+
+  /// @brief
+  /// Perform a complete write transaction on the bus with optional stop
+  /// condition.
+  /// @param address Address in 8-bit format.
+  /// @param data Data to write to the bus.
+  /// @param sendStop
+  /// True to send a stop condition or false to set up a repeated start.
+  error_code writePacket(uint_least8_t address, span<const uint_least8_t> data,
+                         bool sendStop = true) {
+    return doWritePacket(address, data, sendStop);
+  }
+
+  /// @brief Read data byte from the bus.
+  /// @param status Determines whether an ACK or NACK is sent after reading.
+  /// @param[out] data Data read from the bus if successful.
+  virtual error_code readByte(AckStatus status, uint_least8_t & data) = 0;
+
+  /// @brief Read data block from the bus.
+  /// @param status Determines whether an ACK or NACK is sent after reading.
+  /// @param[out] data Data read from the bus if successful.
+  MaximInterfaceCore_EXPORT virtual error_code
+  readBlock(AckStatus status, span<uint_least8_t> data);
+
+  /// @brief
+  /// Perform a complete read transaction on the bus with optional stop
+  /// condition.
+  /// @param address Address in 8-bit format.
+  /// @param[out] data Data read from the bus if successful.
+  /// @param sendStop
+  /// True to send a stop condition or false to set up a repeated start.
+  error_code readPacket(uint_least8_t address, span<uint_least8_t> data,
+                        bool sendStop = true) {
+    return doReadPacket(address, data, sendStop);
+  }
+
+  MaximInterfaceCore_EXPORT static const error_category & errorCategory();
+
+protected:
+  MaximInterfaceCore_EXPORT virtual error_code
+  doWritePacket(uint_least8_t address, span<const uint_least8_t> data,
+                bool sendStop);
+
+  MaximInterfaceCore_EXPORT virtual error_code
+  doReadPacket(uint_least8_t address, span<uint_least8_t> data, bool sendStop);
+};
+
+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 MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/I2CMasterDecorator.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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.
+*******************************************************************************/
+
+#include "I2CMasterDecorator.hpp"
+
+namespace MaximInterfaceCore {
+
+error_code I2CMasterDecorator::start(uint_least8_t address) {
+  return master->start(address);
+}
+
+error_code I2CMasterDecorator::stop() { return master->stop(); }
+
+error_code I2CMasterDecorator::writeByte(uint_least8_t data) {
+  return master->writeByte(data);
+}
+
+error_code I2CMasterDecorator::writeBlock(span<const uint_least8_t> data) {
+  return master->writeBlock(data);
+}
+
+error_code I2CMasterDecorator::doWritePacket(uint_least8_t address,
+                                             span<const uint_least8_t> data,
+                                             bool sendStop) {
+  return master->writePacket(address, data, sendStop);
+}
+
+error_code I2CMasterDecorator::readByte(AckStatus status,
+                                        uint_least8_t & data) {
+  return master->readByte(status, data);
+}
+
+error_code I2CMasterDecorator::readBlock(AckStatus status,
+                                         span<uint_least8_t> data) {
+  return master->readBlock(status, data);
+}
+
+error_code I2CMasterDecorator::doReadPacket(uint_least8_t address,
+                                            span<uint_least8_t> data,
+                                            bool sendStop) {
+  return master->readPacket(address, data, sendStop);
+}
+
+} // namespace MaximInterfaceCore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/I2CMasterDecorator.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 MaximInterfaceCore_I2CMasterDecorator
+#define MaximInterfaceCore_I2CMasterDecorator
+
+#include "Config.hpp"
+#include "I2CMaster.hpp"
+
+namespace MaximInterfaceCore {
+
+class I2CMasterDecorator : public I2CMaster {
+protected:
+  explicit I2CMasterDecorator(I2CMaster & master) : master(&master) {}
+
+public:
+  void setMaster(I2CMaster & master) { this->master = &master; }
+
+  MaximInterfaceCore_EXPORT virtual error_code start(uint_least8_t address);
+
+  MaximInterfaceCore_EXPORT virtual error_code stop();
+
+  MaximInterfaceCore_EXPORT virtual error_code writeByte(uint_least8_t data);
+
+  MaximInterfaceCore_EXPORT virtual error_code
+  writeBlock(span<const uint_least8_t> data);
+
+  MaximInterfaceCore_EXPORT virtual error_code readByte(AckStatus status,
+                                                        uint_least8_t & data);
+
+  MaximInterfaceCore_EXPORT virtual error_code
+  readBlock(AckStatus status, span<uint_least8_t> data);
+
+protected:
+  MaximInterfaceCore_EXPORT virtual error_code
+  doWritePacket(uint_least8_t address, span<const uint_least8_t> data,
+                bool sendStop);
+
+  MaximInterfaceCore_EXPORT virtual error_code
+  doReadPacket(uint_least8_t address, span<uint_least8_t> data, bool sendStop);
+
+private:
+  I2CMaster * master;
+};
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/LoggingI2CMaster.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,138 @@
+/*******************************************************************************
+* 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 "HexConversions.hpp"
+#include "LoggingI2CMaster.hpp"
+
+using std::string;
+
+namespace MaximInterfaceCore {
+
+static const char startString[] = "S ";
+static const char stopString[] = "P";
+
+static string formatDataString(span<const uint_least8_t> data, bool read) {
+  string dataBuilder;
+  for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) {
+    if (read) {
+      dataBuilder.append(1, '[');
+    }
+    dataBuilder.append(byteArrayToHexString(data.subspan(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(make_span(&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(make_span(&data, 1), false));
+  return I2CMasterDecorator::writeByte(data);
+}
+
+error_code LoggingI2CMaster::writeBlock(span<const uint_least8_t> data) {
+  messageBuilder.append(formatDataString(data, false));
+  return I2CMasterDecorator::writeBlock(data);
+}
+
+error_code LoggingI2CMaster::doWritePacket(uint_least8_t address,
+                                           span<const uint_least8_t> data,
+                                           bool sendStop) {
+  messageBuilder.append(startString);
+  messageBuilder.append(formatDataString(make_span(&address, 1), false));
+  error_code result =
+      I2CMasterDecorator::doWritePacket(address, data, sendStop);
+  if (!result) {
+    messageBuilder.append(formatDataString(data, 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(make_span(&data, 1), true));
+  }
+  return result;
+}
+
+error_code LoggingI2CMaster::readBlock(AckStatus status,
+                                       span<uint_least8_t> data) {
+  error_code result = I2CMasterDecorator::readBlock(status, data);
+  if (!result) {
+    messageBuilder.append(formatDataString(data, true));
+  }
+  return result;
+}
+
+error_code LoggingI2CMaster::doReadPacket(uint_least8_t address,
+                                          span<uint_least8_t> data,
+                                          bool sendStop) {
+  messageBuilder.append(startString);
+  messageBuilder.append(formatDataString(make_span(&address, 1), false));
+  error_code result = I2CMasterDecorator::doReadPacket(address, data, sendStop);
+  if (!result) {
+    messageBuilder.append(formatDataString(data, true));
+  }
+  if (sendStop || result) {
+    messageBuilder.append(stopString);
+    tryWriteMessage();
+  }
+  return result;
+}
+
+} // namespace MaximInterfaceCore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/LoggingI2CMaster.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,84 @@
+/*******************************************************************************
+* 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 MaximInterfaceCore_LoggingI2CMaster
+#define MaximInterfaceCore_LoggingI2CMaster
+
+#include <string>
+#include "Config.hpp"
+#include "I2CMasterDecorator.hpp"
+#include "WriteMessage.hpp"
+
+namespace MaximInterfaceCore {
+
+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;
+  }
+
+  MaximInterfaceCore_EXPORT virtual error_code start(uint_least8_t address);
+
+  MaximInterfaceCore_EXPORT virtual error_code stop();
+
+  MaximInterfaceCore_EXPORT virtual error_code writeByte(uint_least8_t data);
+
+  MaximInterfaceCore_EXPORT virtual error_code
+  writeBlock(span<const uint_least8_t> data);
+
+  MaximInterfaceCore_EXPORT virtual error_code readByte(AckStatus status,
+                                                        uint_least8_t & data);
+  MaximInterfaceCore_EXPORT virtual error_code
+  readBlock(AckStatus status, span<uint_least8_t> data);
+
+protected:
+  MaximInterfaceCore_EXPORT virtual error_code
+  doWritePacket(uint_least8_t address, span<const uint_least8_t> data,
+                bool sendStop);
+
+  MaximInterfaceCore_EXPORT virtual error_code
+  doReadPacket(uint_least8_t address, span<uint_least8_t> data, bool sendStop);
+
+private:
+  void tryWriteMessage();
+
+  WriteMessage writeMessage;
+  std::string messageBuilder;
+};
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/LoggingOneWireMaster.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,144 @@
+/*******************************************************************************
+* 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 "HexConversions.hpp"
+#include "LoggingOneWireMaster.hpp"
+
+using std::string;
+
+namespace MaximInterfaceCore {
+
+static const char strongLevelString[] = "<SP_ON>";
+
+static string formatDataString(span<const uint_least8_t> data, bool read) {
+  string dataBuilder;
+  for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) {
+    if (read) {
+      dataBuilder.append(1, '[');
+    }
+    dataBuilder.append(byteArrayToHexString(data.subspan(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(make_span(&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(make_span(&recvByte, 1), true));
+    if (afterLevel == StrongLevel) {
+      tryWriteMessage(strongLevelString);
+    }
+  }
+  return result;
+}
+
+error_code LoggingOneWireMaster::writeBlock(span<const uint_least8_t> sendBuf) {
+  tryWriteMessage(formatDataString(sendBuf, false));
+  return OneWireMasterDecorator::writeBlock(sendBuf);
+}
+
+error_code LoggingOneWireMaster::readBlock(span<uint_least8_t> recvBuf) {
+  error_code result = OneWireMasterDecorator::readBlock(recvBuf);
+  if (!result) {
+    tryWriteMessage(formatDataString(recvBuf, 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 MaximInterfaceCore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/LoggingOneWireMaster.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,80 @@
+/*******************************************************************************
+* 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 MaximInterfaceCore_LoggingOneWireMaster
+#define MaximInterfaceCore_LoggingOneWireMaster
+
+#include <string>
+#include "Config.hpp"
+#include "OneWireMasterDecorator.hpp"
+#include "WriteMessage.hpp"
+
+namespace MaximInterfaceCore {
+
+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;
+  }
+
+  MaximInterfaceCore_EXPORT virtual error_code reset();
+
+  MaximInterfaceCore_EXPORT virtual error_code
+  writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
+
+  MaximInterfaceCore_EXPORT virtual error_code
+  readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+
+  MaximInterfaceCore_EXPORT virtual error_code
+  writeBlock(span<const uint_least8_t> sendBuf);
+
+  MaximInterfaceCore_EXPORT virtual error_code
+  readBlock(span<uint_least8_t> recvBuf);
+
+  MaximInterfaceCore_EXPORT virtual error_code setSpeed(Speed newSpeed);
+
+  MaximInterfaceCore_EXPORT virtual error_code setLevel(Level newLevel);
+
+private:
+  void tryWriteMessage(const std::string & message);
+
+  WriteMessage writeMessage;
+};
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/LoggingSleep.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 MaximInterfaceCore {
+
+void LoggingSleep::invoke(int ms) const {
+  if (writeMessage) {
+    std::ostringstream message;
+    message << "<DELAY" << ms << '>';
+    writeMessage(message.str());
+  }
+  SleepDecorator::invoke(ms);
+}
+
+} // namespace MaximInterfaceCore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/LoggingSleep.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 MaximInterfaceCore_LoggingSleep
+#define MaximInterfaceCore_LoggingSleep
+
+#include "Config.hpp"
+#include "SleepDecorator.hpp"
+#include "WriteMessage.hpp"
+
+namespace MaximInterfaceCore {
+
+class LoggingSleep : public SleepDecorator {
+public:
+  LoggingSleep(Sleep & sleep,
+               const WriteMessage & writeMessage = WriteMessage())
+      : SleepDecorator(sleep), writeMessage(writeMessage) {}
+
+  void setWriteMessage(const WriteMessage & writeMessage) {
+    this->writeMessage = writeMessage;
+  }
+
+  MaximInterfaceCore_EXPORT virtual void invoke(int ms) const;
+
+private:
+  WriteMessage writeMessage;
+};
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/ManId.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 MaximInterfaceCore_ManId
+#define MaximInterfaceCore_ManId
+
+#include "array_span.hpp"
+
+namespace MaximInterfaceCore {
+
+/// Standard container for a manufacturer ID.
+typedef array_span<uint_least8_t, 2> ManId;
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/None.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,48 @@
+/*******************************************************************************
+* Copyright (C) 2019 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 MaximInterfaceCore_None
+#define MaximInterfaceCore_None
+
+namespace MaximInterfaceCore {
+
+struct None {
+  // Disable default constructor.
+  explicit None(int) {}
+};
+
+/// Empty tag for use with Optional and similar types.
+static const None none(0);
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/OneWireMaster.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,130 @@
+/*******************************************************************************
+* 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 MaximInterfaceCore {
+
+static const int maxBitNum = 7;
+
+error_code OneWireMaster::writeByteSetLevel(uint_least8_t sendByte,
+                                            Level afterLevel) {
+  error_code result;
+  for (int bitNum = 0; (bitNum <= maxBitNum) && !result; ++bitNum) {
+    result = writeBitSetLevel(((sendByte >> bitNum) & 1) == 1,
+                              (bitNum == maxBitNum) ? afterLevel : NormalLevel);
+  }
+  return result;
+}
+
+error_code OneWireMaster::readByteSetLevel(uint_least8_t & recvByte,
+                                           Level afterLevel) {
+  recvByte = 0;
+  error_code result;
+  for (int bitNum = 0; bitNum <= maxBitNum; ++bitNum) {
+    bool recvBit;
+    result = readBitSetLevel(recvBit,
+                             (bitNum == maxBitNum) ? afterLevel : NormalLevel);
+    if (result) {
+      break;
+    }
+    if (recvBit) {
+      recvByte |= (1 << bitNum);
+    }
+  }
+  return result;
+}
+
+error_code OneWireMaster::writeBlock(span<const uint_least8_t> sendBuf) {
+  error_code result;
+  for (span<const uint_least8_t>::index_type i = 0;
+       i < sendBuf.size() && !result; ++i) {
+    result = writeByte(sendBuf[i]);
+  }
+  return result;
+}
+
+error_code OneWireMaster::readBlock(span<uint_least8_t> recvBuf) {
+  error_code result;
+  for (span<uint_least8_t>::index_type i = 0; i < recvBuf.size() && !result;
+       ++i) {
+    result = readByte(recvBuf[i]);
+  }
+  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 MaximInterfaceCore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/OneWireMaster.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,190 @@
+/*******************************************************************************
+* 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 MaximInterfaceCore_OneWireMaster
+#define MaximInterfaceCore_OneWireMaster
+
+#include <stdint.h>
+#include "Config.hpp"
+#include "span.hpp"
+#include "system_error.hpp"
+
+namespace MaximInterfaceCore {
+
+/// 1-Wire master interface.
+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() {}
+
+  /// @brief
+  /// 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;
+
+  /// @brief
+  /// 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;
+
+  /// @brief
+  /// 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.
+  MaximInterfaceCore_EXPORT virtual error_code
+  writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
+
+  /// @brief
+  /// 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.
+  MaximInterfaceCore_EXPORT virtual error_code
+  readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+
+  /// @brief Send a block of communication on the 1-Wire bus.
+  /// @param[in] sendBuf Buffer to send on the 1-Wire bus.
+  MaximInterfaceCore_EXPORT virtual error_code
+  writeBlock(span<const uint_least8_t> sendBuf);
+
+  /// @brief Receive a block of communication on the 1-Wire bus.
+  /// @param[out] recvBuf Buffer to receive the data from the 1-Wire bus.
+  MaximInterfaceCore_EXPORT virtual error_code
+  readBlock(span<uint_least8_t> recvBuf);
+
+  /// 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;
+
+  /// @brief 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.
+  MaximInterfaceCore_EXPORT virtual error_code triplet(TripletData & data);
+
+  /// @brief
+  /// 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);
+  }
+
+  /// @brief
+  /// 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 touchBit(bool & sendRecvBit) {
+    return touchBitSetLevel(sendRecvBit, NormalLevel);
+  }
+
+  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);
+  }
+
+  MaximInterfaceCore_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 MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/OneWireMasterDecorator.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 "OneWireMasterDecorator.hpp"
+
+namespace MaximInterfaceCore {
+
+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(span<const uint_least8_t> sendBuf) {
+  return master->writeBlock(sendBuf);
+}
+
+error_code OneWireMasterDecorator::readBlock(span<uint_least8_t> recvBuf) {
+  return master->readBlock(recvBuf);
+}
+
+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 MaximInterfaceCore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/OneWireMasterDecorator.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 MaximInterfaceCore_OneWireMasterDecorator
+#define MaximInterfaceCore_OneWireMasterDecorator
+
+#include "Config.hpp"
+#include "OneWireMaster.hpp"
+
+namespace MaximInterfaceCore {
+
+class OneWireMasterDecorator : public OneWireMaster {
+protected:
+  explicit OneWireMasterDecorator(OneWireMaster & master) : master(&master) {}
+
+public:
+  void setMaster(OneWireMaster & master) { this->master = &master; }
+
+  MaximInterfaceCore_EXPORT virtual error_code reset();
+
+  MaximInterfaceCore_EXPORT virtual error_code
+  touchBitSetLevel(bool & sendRecvBit, Level afterLevel);
+
+  MaximInterfaceCore_EXPORT virtual error_code
+  writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
+
+  MaximInterfaceCore_EXPORT virtual error_code
+  readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+
+  MaximInterfaceCore_EXPORT virtual error_code
+  writeBlock(span<const uint_least8_t> sendBuf);
+
+  MaximInterfaceCore_EXPORT virtual error_code
+  readBlock(span<uint_least8_t> recvBuf);
+
+  MaximInterfaceCore_EXPORT virtual error_code setSpeed(Speed newSpeed);
+
+  MaximInterfaceCore_EXPORT virtual error_code setLevel(Level newLevel);
+
+  MaximInterfaceCore_EXPORT virtual error_code triplet(TripletData & data);
+
+private:
+  OneWireMaster * master;
+};
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/Optional.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,307 @@
+/*******************************************************************************
+* Copyright (C) 2018 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 MaximInterfaceCore_Optional
+#define MaximInterfaceCore_Optional
+
+#include "None.hpp"
+#include "SafeBool.hpp"
+
+// Include for std::swap.
+#include <algorithm>
+#include <utility>
+
+namespace MaximInterfaceCore {
+
+/// @brief Optional value container similar to std::optional.
+/// @details
+/// To prevent the need for aligned storage, this implementation imposes that
+/// types must be DefaultConstructible, CopyConstructible, and CopyAssignable.
+/// No exceptions are thrown when accessing a valueless Optional.
+template <typename T> class Optional {
+public:
+  typedef T value_type;
+
+  Optional() : value_(), hasValue_(false) {}
+
+  Optional(None) : value_(), hasValue_(false) {}
+
+  Optional(const T & value) : value_(value), hasValue_(true) {}
+
+  template <typename U>
+  explicit Optional(const Optional<U> & other)
+      : value_(other.value()), hasValue_(other.hasValue()) {}
+
+  Optional & operator=(None) {
+    reset();
+    return *this;
+  }
+
+  template <typename U> Optional & operator=(const Optional<U> & other) {
+    if (hasValue_ || other.hasValue()) {
+      value_ = other.value();
+      hasValue_ = other.hasValue();
+    }
+    return *this;
+  }
+
+  bool hasValue() const { return hasValue_; }
+
+  operator SafeBool() const { return makeSafeBool(hasValue()); }
+
+  const T & value() const { return value_; }
+
+  T & value() {
+    return const_cast<T &>(static_cast<const Optional &>(*this).value());
+  }
+
+  const T & operator*() const { return value(); }
+
+  T & operator*() {
+    return const_cast<T &>(static_cast<const Optional &>(*this).operator*());
+  }
+
+  const T * operator->() const { return &value(); }
+
+  T * operator->() {
+    return const_cast<T *>(static_cast<const Optional &>(*this).operator->());
+  }
+
+  const T & valueOr(const T & defaultValue) const {
+    return hasValue() ? value() : defaultValue;
+  }
+
+  void swap(Optional & other) {
+    if (hasValue_ || other.hasValue_) {
+      using std::swap;
+      swap(value_, other.value_);
+      swap(hasValue_, other.hasValue_);
+    }
+  }
+
+  void reset() {
+    if (hasValue_) {
+      hasValue_ = false;
+      value_ = T();
+    }
+  }
+
+private:
+  T value_;
+  bool hasValue_;
+};
+
+template <typename T> Optional<T> makeOptional(const T & value) {
+  return value;
+}
+
+template <typename T> void swap(Optional<T> & lhs, Optional<T> & rhs) {
+  lhs.swap(rhs);
+}
+
+template <typename T, typename U>
+bool operator==(const Optional<T> & lhs, const Optional<U> & rhs) {
+  if (lhs.hasValue() != rhs.hasValue()) {
+    return false;
+  }
+  if (!lhs.hasValue()) {
+    return true;
+  }
+  return lhs.value() == rhs.value();
+}
+
+template <typename T, typename U>
+bool operator!=(const Optional<T> & lhs, const Optional<U> & rhs) {
+  if (lhs.hasValue() != rhs.hasValue()) {
+    return true;
+  }
+  if (!lhs.hasValue()) {
+    return false;
+  }
+  return lhs.value() != rhs.value();
+}
+
+template <typename T, typename U>
+bool operator<(const Optional<T> & lhs, const Optional<U> & rhs) {
+  if (!rhs.hasValue()) {
+    return false;
+  }
+  if (!lhs.hasValue()) {
+    return true;
+  }
+  return lhs.value() < rhs.value();
+}
+
+template <typename T, typename U>
+bool operator<=(const Optional<T> & lhs, const Optional<U> & rhs) {
+  if (!lhs.hasValue()) {
+    return true;
+  }
+  if (!rhs.hasValue()) {
+    return false;
+  }
+  return lhs.value() <= rhs.value();
+}
+
+template <typename T, typename U>
+bool operator>(const Optional<T> & lhs, const Optional<U> & rhs) {
+  if (!lhs.hasValue()) {
+    return false;
+  }
+  if (!rhs.hasValue()) {
+    return true;
+  }
+  return lhs.value() > rhs.value();
+}
+
+template <typename T, typename U>
+bool operator>=(const Optional<T> & lhs, const Optional<U> & rhs) {
+  if (!rhs.hasValue()) {
+    return true;
+  }
+  if (!lhs.hasValue()) {
+    return false;
+  }
+  return lhs.value() >= rhs.value();
+}
+
+template <typename T> bool operator==(const Optional<T> & opt, None) {
+  return !opt.hasValue();
+}
+
+template <typename T> bool operator==(None, const Optional<T> & opt) {
+  return operator==(opt, none);
+}
+
+template <typename T> bool operator!=(const Optional<T> & opt, None) {
+  return !operator==(opt, none);
+}
+
+template <typename T> bool operator!=(None, const Optional<T> & opt) {
+  return operator!=(opt, none);
+}
+
+template <typename T> bool operator<(const Optional<T> &, None) {
+  return false;
+}
+
+template <typename T> bool operator<(None, const Optional<T> & opt) {
+  return opt.hasValue();
+}
+
+template <typename T> bool operator<=(const Optional<T> & opt, None) {
+  return !operator>(opt, none);
+}
+
+template <typename T> bool operator<=(None, const Optional<T> & opt) {
+  return !operator>(none, opt);
+}
+
+template <typename T> bool operator>(const Optional<T> & opt, None) {
+  return operator<(none, opt);
+}
+
+template <typename T> bool operator>(None, const Optional<T> & opt) {
+  return operator<(opt, none);
+}
+
+template <typename T> bool operator>=(const Optional<T> & opt, None) {
+  return !operator<(opt, none);
+}
+
+template <typename T> bool operator>=(None, const Optional<T> & opt) {
+  return !operator<(none, opt);
+}
+
+template <typename T, typename U>
+bool operator==(const Optional<T> & opt, const U & value) {
+  return opt.hasValue() ? opt.value() == value : false;
+}
+
+template <typename T, typename U>
+bool operator==(const T & value, const Optional<U> & opt) {
+  return operator==(opt, value);
+}
+
+template <typename T, typename U>
+bool operator!=(const Optional<T> & opt, const U & value) {
+  return opt.hasValue() ? opt.value() != value : true;
+}
+
+template <typename T, typename U>
+bool operator!=(const T & value, const Optional<U> & opt) {
+  return operator!=(opt, value);
+}
+
+template <typename T, typename U>
+bool operator<(const Optional<T> & opt, const U & value) {
+  return opt.hasValue() ? opt.value() < value : true;
+}
+
+template <typename T, typename U>
+bool operator<(const T & value, const Optional<U> & opt) {
+  return opt.hasValue() ? value < opt.value() : false;
+}
+
+template <typename T, typename U>
+bool operator<=(const Optional<T> & opt, const U & value) {
+  return opt.hasValue() ? opt.value() <= value : true;
+}
+
+template <typename T, typename U>
+bool operator<=(const T & value, const Optional<U> & opt) {
+  return opt.hasValue() ? value <= opt.value() : false;
+}
+
+template <typename T, typename U>
+bool operator>(const Optional<T> & opt, const U & value) {
+  return opt.hasValue() ? opt.value() > value : false;
+}
+
+template <typename T, typename U>
+bool operator>(const T & value, const Optional<U> & opt) {
+  return opt.hasValue() ? value > opt.value() : true;
+}
+
+template <typename T, typename U>
+bool operator>=(const Optional<T> & opt, const U & value) {
+  return opt.hasValue() ? opt.value() >= value : false;
+}
+
+template <typename T, typename U>
+bool operator>=(const T & value, const Optional<U> & opt) {
+  return opt.hasValue() ? value >= opt.value() : true;
+}
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/RomCommands.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,210 @@
+/*******************************************************************************
+* 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 "RomCommands.hpp"
+
+namespace MaximInterfaceCore {
+
+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, RomId::const_span romId) {
+  SearchRomState searchState(romId);
+  error_code result = searchRom(master, searchState);
+  if (result) {
+    return result;
+  }
+  // Check if same device found.
+  if (!equal(romId, make_span(searchState.romId))) {
+    result = make_error_code(OneWireMaster::NoSlaveError);
+  }
+  return result;
+}
+
+error_code readRom(OneWireMaster & master, RomId::span romId) {
+  error_code result = master.reset();
+  if (result) {
+    return result;
+  }
+  result = master.writeByte(ReadRomCmd);
+  if (result) {
+    return result;
+  }
+  result = master.readBlock(romId);
+  if (result) {
+    return result;
+  }
+  if (!valid(romId)) {
+    result = make_error_code(OneWireMaster::NoSlaveError);
+  }
+  return result;
+}
+
+error_code skipRom(OneWireMaster & master) {
+  error_code result = master.reset();
+  if (result) {
+    return result;
+  }
+  result = master.writeByte(SkipRomCmd);
+  return result;
+}
+
+error_code matchRom(OneWireMaster & master, RomId::const_span romId) {
+  error_code result = master.reset();
+  if (result) {
+    return result;
+  }
+  result = master.writeByte(MatchRomCmd);
+  if (result) {
+    return result;
+  }
+  result = master.writeBlock(romId);
+  return result;
+}
+
+error_code overdriveSkipRom(OneWireMaster & master) {
+  error_code result = master.reset();
+  if (result) {
+    return result;
+  }
+  result = master.writeByte(OverdriveSkipRomCmd);
+  if (result) {
+    return result;
+  }
+  result = master.setSpeed(OneWireMaster::OverdriveSpeed);
+  return result;
+}
+
+error_code overdriveMatchRom(OneWireMaster & master, RomId::const_span romId) {
+  error_code result = master.reset();
+  if (result) {
+    return result;
+  }
+  result = master.writeByte(OverdriveMatchRomCmd);
+  if (result) {
+    return result;
+  }
+  result = master.setSpeed(OneWireMaster::OverdriveSpeed);
+  if (result) {
+    return result;
+  }
+  result = master.writeBlock(romId);
+  return result;
+}
+
+error_code resumeRom(OneWireMaster & master) {
+  error_code result = master.reset();
+  if (result) {
+    return 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;
+  newSearchState.lastFamilyDiscrepancy = searchState.lastFamilyDiscrepancy;
+  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 == searchState.lastDiscrepancy) {
+      tripletData.writeBit = 1;
+    } else if (idBitNumber > searchState.lastDiscrepancy) {
+      tripletData.writeBit = 0;
+    } else { // idBitNumber < searchState.lastDiscrepancy
+      tripletData.writeBit =
+          (searchState.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 if (!tripletData.readBit && !tripletData.readBitComplement) {
+      newSearchState.lastDiscrepancy = idBitNumber;
+      if (idBitNumber <= 8) {
+        newSearchState.lastFamilyDiscrepancy = idBitNumber;
+      }
+    }
+  }
+
+  if (valid(newSearchState.romId)) {
+    if (newSearchState.lastDiscrepancy == 0) {
+      newSearchState.lastDevice = true;
+    }
+    searchState = newSearchState;
+  } else {
+    result = make_error_code(OneWireMaster::NoSlaveError);
+  }
+  return result;
+}
+
+} // namespace MaximInterfaceCore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/RomCommands.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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.
+*******************************************************************************/
+
+/// @file
+/// @brief ROM Commands for enumerating and selecting 1-Wire devices.
+
+#ifndef MaximInterfaceCore_RomCommands
+#define MaximInterfaceCore_RomCommands
+
+#include <stdint.h>
+#include "Algorithm.hpp"
+#include "Config.hpp"
+#include "OneWireMaster.hpp"
+#include "RomId.hpp"
+
+namespace MaximInterfaceCore {
+
+/// State used by Search ROM command.
+struct SearchRomState {
+  RomId::array romId;
+  int_least8_t lastDiscrepancy;
+  int_least8_t lastFamilyDiscrepancy;
+  bool lastDevice;
+
+  SearchRomState()
+      : romId(), lastDiscrepancy(0), lastFamilyDiscrepancy(0),
+        lastDevice(false) {}
+
+  explicit SearchRomState(RomId::const_span romId)
+      : lastDiscrepancy(64), lastFamilyDiscrepancy(0), lastDevice(false) {
+    copy(romId, make_span(this->romId));
+  }
+
+  explicit SearchRomState(RomId::element familyCode)
+      : romId(), lastDiscrepancy(64), lastFamilyDiscrepancy(0),
+        lastDevice(false) {
+    setFamilyCode(romId, familyCode);
+  }
+};
+
+/// @brief
+/// Set the search state to skip the current device family on the next
+/// Search ROM command.
+MaximInterfaceCore_EXPORT void skipCurrentFamily(SearchRomState & searchState);
+
+/// Verify that the device with the specified ROM ID is present.
+MaximInterfaceCore_EXPORT error_code verifyRom(OneWireMaster & master,
+                                               RomId::const_span romId);
+
+/// @brief 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 there is more than one device on the bus.
+/// @param master 1-Wire master for operation.
+/// @param[out] romId ROM ID read from device.
+MaximInterfaceCore_EXPORT error_code readRom(OneWireMaster & master,
+                                             RomId::span romId);
+
+/// @brief Issue Skip ROM command on bus.
+/// @note
+/// Only use this command with a single-drop bus.
+/// Data collisions will occur if there is more than one device on the bus.
+MaximInterfaceCore_EXPORT error_code skipRom(OneWireMaster & master);
+
+/// @brief 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 master 1-Wire master for operation.
+/// @param[in] romId ROM ID of device to select.
+MaximInterfaceCore_EXPORT error_code matchRom(OneWireMaster & master,
+                                              RomId::const_span romId);
+
+/// @brief 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 there is more than one device on the bus.
+MaximInterfaceCore_EXPORT error_code overdriveSkipRom(OneWireMaster & master);
+
+/// @brief
+/// Use the Overdrive Match ROM command to select the device by its known ID.
+/// @param master 1-Wire master for operation.
+/// @param[in] romId ROM ID of device to select.
+MaximInterfaceCore_EXPORT error_code overdriveMatchRom(OneWireMaster & master,
+                                                       RomId::const_span romId);
+
+/// @brief Perform a Resume ROM command on bus.
+/// @details
+/// Resumes communication with the last device selected through a Match ROM or
+/// Search ROM operation.
+MaximInterfaceCore_EXPORT error_code resumeRom(OneWireMaster & master);
+
+/// @brief 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.
+MaximInterfaceCore_EXPORT error_code searchRom(OneWireMaster & master,
+                                               SearchRomState & searchState);
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/RomId.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,80 @@
+/*******************************************************************************
+* 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 MaximInterfaceCore_RomId
+#define MaximInterfaceCore_RomId
+
+#include "array_span.hpp"
+#include "crc.hpp"
+
+namespace MaximInterfaceCore {
+
+/// Standard container for a 1-Wire ROM ID.
+typedef array_span<uint_least8_t, 8> RomId;
+
+/// @name Family Code
+/// @{
+
+/// Get the Family Code byte.
+inline RomId::element familyCode(RomId::const_span romId) { return romId[0]; }
+
+/// Set the Family Code byte.
+inline void setFamilyCode(RomId::span romId, RomId::element familyCode) {
+  romId[0] = familyCode;
+}
+
+/// @}
+
+/// @name CRC8
+/// @{
+
+/// Get the CRC8 byte.
+inline RomId::element crc8(RomId::const_span romId) {
+  return *romId.last<1>().data();
+}
+
+/// Set the CRC8 byte.
+inline void setCrc8(RomId::span romId, RomId::element crc8) {
+  *romId.last<1>().data() = crc8;
+}
+
+/// @}
+
+/// @brief 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(RomId::const_span romId) {
+  return calculateCrc8(romId.first(romId.size() - 1)) == crc8(romId);
+}
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/RunCommand.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,210 @@
+/*******************************************************************************
+* Copyright (C) 2018 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"
+#include "Error.hpp"
+#include "I2CMaster.hpp"
+#include "OneWireMaster.hpp"
+#include "RunCommand.hpp"
+#include "Sleep.hpp"
+
+namespace MaximInterfaceCore {
+
+const error_category & RunCommandWithOneWireMaster::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "RunCommandWithOneWireMaster"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case CrcError:
+        return "CRC Error";
+
+      case InvalidResponseError:
+        return "Invalid Response Error";
+      }
+      return defaultErrorMessage(condition);
+    }
+  } instance;
+  return instance;
+}
+
+error_code RunCommandWithOneWireMaster::
+operator()(span<const uint_least8_t> request, int delayTime,
+           span<uint_least8_t> & response) const {
+  // Write request.
+  error_code result = selectRom(*master);
+  if (result) {
+    return result;
+  }
+  uint_least8_t xpcBuffer[2] = {0x66,
+                                static_cast<uint_least8_t>(request.size())};
+  result = master->writeBlock(xpcBuffer);
+  if (result) {
+    return result;
+  }
+  result = master->writeBlock(request);
+  if (result) {
+    return result;
+  }
+  uint_fast16_t expectedCrc =
+      calculateCrc16(calculateCrc16(xpcBuffer), request) ^ 0xFFFFu;
+  result = master->readBlock(xpcBuffer);
+  if (result) {
+    return result;
+  }
+  if (expectedCrc !=
+      ((static_cast<uint_fast16_t>(xpcBuffer[1]) << 8) | xpcBuffer[0])) {
+    return make_error_code(CrcError);
+  }
+  result = master->writeBytePower(0xAA);
+  if (result) {
+    return result;
+  }
+
+  // Wait for device to process.
+  sleep->invoke(delayTime);
+
+  // Read response.
+  result = master->setLevel(OneWireMaster::NormalLevel);
+  if (result) {
+    return result;
+  }
+  result = master->readBlock(xpcBuffer);
+  if (result) {
+    return result;
+  }
+  if (xpcBuffer[1] > response.size()) {
+    return make_error_code(InvalidResponseError);
+  }
+  response = response.first(xpcBuffer[1]);
+  result = master->readBlock(response);
+  if (result) {
+    return result;
+  }
+  expectedCrc =
+      calculateCrc16(calculateCrc16(make_span(xpcBuffer + 1, 1)), response) ^
+      0xFFFFu;
+  result = master->readBlock(xpcBuffer);
+  if (result) {
+    return result;
+  }
+  if (expectedCrc !=
+      ((static_cast<uint_fast16_t>(xpcBuffer[1]) << 8) | xpcBuffer[0])) {
+    return make_error_code(CrcError);
+  }
+  return result;
+}
+
+const error_category & RunCommandWithI2CMaster::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "RunCommandWithI2CMaster"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case InvalidResponseError:
+        return "Invalid Response Error";
+      }
+      return defaultErrorMessage(condition);
+    }
+  } instance;
+  return instance;
+}
+
+error_code RunCommandWithI2CMaster::
+operator()(span<const uint_least8_t> request, int delayTime,
+           span<uint_least8_t> & response) const {
+  // Write request.
+  error_code result = master->start(address_);
+  if (result == make_error_condition(I2CMaster::NackError) && address_ != 0) {
+    result = master->start(0);
+  }
+  if (result) {
+    master->stop();
+    return result;
+  }
+  if (!request.empty()) {
+    result = master->writeByte(request[0]);
+    if (result) {
+      master->stop();
+      return result;
+    }
+    request = request.subspan(1);
+    if (!request.empty()) {
+      result = master->writeByte(static_cast<uint_least8_t>(request.size()));
+      if (result) {
+        master->stop();
+        return result;
+      }
+      result = master->writeBlock(request);
+      if (result) {
+        master->stop();
+        return result;
+      }
+    }
+  }
+  result = master->stop();
+  if (result) {
+    return result;
+  }
+
+  // Wait for device to process.
+  sleep->invoke(delayTime);
+
+  // Read response.
+  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;
+  }
+  if (length > response.size()) {
+    master->stop();
+    return make_error_code(InvalidResponseError);
+  }
+  response = response.first(length);
+  result = master->readBlock(I2CMaster::Nack, response);
+  if (result) {
+    master->stop();
+    return result;
+  }
+  result = master->stop();
+  return result;
+}
+
+} // namespace MaximInterfaceCore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/RunCommand.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,120 @@
+/*******************************************************************************
+* Copyright (C) 2018 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 MaximInterfaceCore_RunCommand
+#define MaximInterfaceCore_RunCommand
+
+#include "Config.hpp"
+#include "Function.hpp"
+#include "SelectRom.hpp"
+#include "span.hpp"
+#include "system_error.hpp"
+
+namespace MaximInterfaceCore {
+
+class I2CMaster;
+class OneWireMaster;
+class Sleep;
+
+typedef Function<error_code(span<const uint_least8_t>, int,
+                            span<uint_least8_t> &)>
+    RunCommand;
+
+class RunCommandWithOneWireMaster {
+public:
+  typedef RunCommand::result_type result_type;
+
+  enum ErrorValue { CrcError = 1, InvalidResponseError };
+  MaximInterfaceCore_EXPORT static const error_category & errorCategory();
+
+  RunCommandWithOneWireMaster(Sleep & sleep, OneWireMaster & master,
+                              const SelectRom & selectRom)
+      : selectRom(selectRom), master(&master), sleep(&sleep) {}
+
+  void setSleep(Sleep & sleep) { this->sleep = &sleep; }
+
+  void setMaster(OneWireMaster & master) { this->master = &master; }
+
+  void setSelectRom(const SelectRom & selectRom) {
+    this->selectRom = selectRom;
+  }
+
+  MaximInterfaceCore_EXPORT error_code
+  operator()(span<const uint_least8_t> request, int delayTime,
+             span<uint_least8_t> & response) const;
+
+private:
+  SelectRom selectRom;
+  OneWireMaster * master;
+  const Sleep * sleep;
+};
+
+inline error_code make_error_code(RunCommandWithOneWireMaster::ErrorValue e) {
+  return error_code(e, RunCommandWithOneWireMaster::errorCategory());
+}
+
+class RunCommandWithI2CMaster {
+public:
+  typedef RunCommand::result_type result_type;
+
+  enum ErrorValue { InvalidResponseError = 1 };
+  MaximInterfaceCore_EXPORT static const error_category & errorCategory();
+
+  RunCommandWithI2CMaster(Sleep & sleep, I2CMaster & master,
+                          uint_least8_t address)
+      : sleep(&sleep), master(&master), address_(address & 0xFE) {}
+
+  void setSleep(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) { address_ = address & 0xFE; }
+
+  MaximInterfaceCore_EXPORT error_code
+  operator()(span<const uint_least8_t> request, int delayTime,
+             span<uint_least8_t> & response) const;
+
+private:
+  const Sleep * sleep;
+  I2CMaster * master;
+  uint_least8_t address_;
+};
+
+inline error_code make_error_code(RunCommandWithI2CMaster::ErrorValue e) {
+  return error_code(e, RunCommandWithI2CMaster::errorCategory());
+}
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/SafeBool.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,65 @@
+/*******************************************************************************
+* Copyright (C) 2018 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 MaximInterfaceCore_SafeBool
+#define MaximInterfaceCore_SafeBool
+
+#include <stddef.h>
+#include "Unconstructible.hpp"
+
+namespace MaximInterfaceCore {
+namespace detail {
+
+// Implement SafeBool as a member function pointer since some compilers allow
+// function pointer to void pointer conversion.
+struct SafeBoolHelper : Unconstructible {
+  void trueValue() const {}
+};
+
+} // namespace detail
+
+/// @brief Type definition for SafeBool.
+/// @details
+/// SafeBool is a boolean type that eliminates many error-prone implicit
+/// conversions allowed by the fundamental bool type.
+/// @note
+/// SafeBool can be used to add an explicit bool conversion operator to a type.
+typedef void (detail::SafeBoolHelper::*SafeBool)() const;
+
+/// Constructor for SafeBool.
+inline SafeBool makeSafeBool(bool value) {
+  return value ? &detail::SafeBoolHelper::trueValue : NULL;
+}
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/Segment.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,135 @@
+/*******************************************************************************
+* 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 MaximInterfaceCore_Segment
+#define MaximInterfaceCore_Segment
+
+#include <iterator>
+#include <utility>
+#include "type_traits.hpp"
+
+namespace MaximInterfaceCore {
+
+/// @brief
+/// Advances a given iterator by a given number of elements with bounds checking.
+/// @tparam 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;
+}
+
+/// @brief Locates an iterator sub-range using segment number addressing.
+/// @details
+/// Useful for devices that divide the memory space into uniform chunks such as
+/// pages and segments.
+/// @tparam 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 iterator 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 MaximInterfaceCore
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/SelectRom.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 MaximInterfaceCore {
+
+error_code SelectMatchRom::operator()(OneWireMaster & master) const {
+  return matchRom(master, romId_);
+}
+
+error_code SelectMatchRomWithResume::operator()(OneWireMaster & master) const {
+  error_code result;
+  if (romId_ == data->lastRomId) {
+    result = resumeRom(master);
+  } else {
+    result = matchRom(master, romId_);
+    data->lastRomId = romId_;
+  }
+  return result;
+}
+
+} // namespace MaximInterfaceCore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/SelectRom.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,100 @@
+/*******************************************************************************
+* 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 MaximInterfaceCore_SelectRom
+#define MaximInterfaceCore_SelectRom
+
+#include "Config.hpp"
+#include "Function.hpp"
+#include "RomCommands.hpp"
+#include "RomId.hpp"
+#include "system_error.hpp"
+
+namespace MaximInterfaceCore {
+
+class OneWireMaster;
+
+/// Selects a 1-Wire device on the bus for communication.
+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(RomId::const_span romId) { setRomId(romId); }
+
+  RomId::const_span romId() const { return romId_; }
+
+  void setRomId(RomId::const_span romId) { copy(romId, make_span(romId_)); }
+
+  MaximInterfaceCore_EXPORT error_code operator()(OneWireMaster & master) const;
+
+private:
+  RomId::array romId_;
+};
+
+/// @brief
+/// 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 {
+    SharedData() : lastRomId() {}
+    RomId::array lastRomId;
+  };
+
+  SelectMatchRomWithResume(SharedData & data, RomId::const_span romId)
+      : data(&data) {
+    setRomId(romId);
+  }
+
+  void setSharedData(SharedData & data) { this->data = &data; }
+
+  RomId::const_span romId() const { return romId_; }
+
+  void setRomId(RomId::const_span romId) { copy(romId, make_span(romId_)); }
+
+  MaximInterfaceCore_EXPORT error_code operator()(OneWireMaster & master) const;
+
+private:
+  SharedData * data;
+  RomId::array romId_;
+};
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/SerialPort.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 MaximInterfaceCore_SerialPort
+#define MaximInterfaceCore_SerialPort
+
+#include <string>
+#include "Uart.hpp"
+
+namespace MaximInterfaceCore {
+
+class SerialPort : public Uart {
+public:
+  /// Connect a specified COM port.
+  virtual error_code connect(const std::string & portName) = 0;
+
+  /// Disconnect from the current port.
+  virtual error_code disconnect() = 0;
+
+  /// @brief Check if currently connected to a port.
+  /// @returns True if connected.
+  virtual bool connected() const = 0;
+
+  /// Get the currently connected port name.
+  virtual std::string portName() const = 0;
+};
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/Sleep.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 MaximInterfaceCore_Sleep
+#define MaximInterfaceCore_Sleep
+
+namespace MaximInterfaceCore {
+
+class Sleep {
+public:
+  virtual ~Sleep() {}
+  virtual void invoke(int ms) const = 0;
+  void operator()(int ms) const { invoke(ms); }
+};
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/SleepDecorator.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 MaximInterfaceCore {
+
+void SleepDecorator::invoke(int ms) const { sleep->invoke(ms); }
+
+} // namespace MaximInterfaceCore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/SleepDecorator.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 MaximInterfaceCore_SleepDecorator
+#define MaximInterfaceCore_SleepDecorator
+
+#include "Config.hpp"
+#include "Sleep.hpp"
+
+namespace MaximInterfaceCore {
+
+class SleepDecorator : public Sleep {
+protected:
+  explicit SleepDecorator(Sleep & sleep) : sleep(&sleep) {}
+
+public:
+  void setSleep(Sleep & sleep) { this->sleep = &sleep; }
+  MaximInterfaceCore_EXPORT virtual void invoke(int ms) const;
+
+private:
+  const Sleep * sleep;
+};
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/Uart.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 "Error.hpp"
+#include "Uart.hpp"
+
+namespace MaximInterfaceCore {
+
+error_code Uart::writeBlock(span<const uint_least8_t> data) {
+  error_code result;
+  for (span<const uint_least8_t>::index_type i = 0;
+       i < data.size() && !result; ++i) {
+    result = writeByte(data[i]);
+  }
+  return result;
+}
+
+error_code Uart::readBlock(span<uint_least8_t> data) {
+  error_code result;
+  for (span<uint_least8_t>::index_type i = 0; i < data.size() && !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 MaximInterfaceCore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/Uart.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,95 @@
+/*******************************************************************************
+* 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 MaximInterfaceCore_Uart
+#define MaximInterfaceCore_Uart
+
+#include <stdint.h>
+#include "Config.hpp"
+#include "span.hpp"
+#include "system_error.hpp"
+
+namespace MaximInterfaceCore {
+
+/// Universal asynchronous receiver-transmitter interface.
+class Uart {
+public:
+  enum ErrorValue {
+    TimeoutError = 1, ///< Read operation aborted due to timeout.
+    OverrunError      ///< Received data lost due to read buffer overrun.
+  };
+
+  virtual ~Uart() {}
+
+  /// Set the baud rate of the port in Hz.
+  virtual error_code setBaudRate(int_least32_t baudRate) = 0;
+
+  /// Generate a break condition on the port for a small amount of time.
+  virtual error_code sendBreak() = 0;
+
+  /// Clear all received data that was buffered.
+  virtual error_code clearReadBuffer() = 0;
+
+  /// Writes a byte of data to the port.
+  virtual error_code writeByte(uint_least8_t data) = 0;
+
+  /// Writes a block of data to the port.
+  MaximInterfaceCore_EXPORT virtual error_code
+  writeBlock(span<const uint_least8_t> data);
+
+  /// @brief
+  /// Reads a byte of data from the port. Block until data is received or a
+  /// timeout is reached.
+  /// @param[out] data Data read from the port if successful.
+  virtual error_code readByte(uint_least8_t & data) = 0;
+
+  /// @brief
+  /// Read a block of data from the port. Block until data is received or a
+  /// timeout is reached.
+  /// @param[out] data Data read from the port if successful.
+  MaximInterfaceCore_EXPORT virtual error_code
+  readBlock(span<uint_least8_t> data);
+
+  MaximInterfaceCore_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 MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/Unconstructible.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,45 @@
+/*******************************************************************************
+* Copyright (C) 2019 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 MaximInterfaceCore_Unconstructible
+#define MaximInterfaceCore_Unconstructible
+
+namespace MaximInterfaceCore {
+
+struct Unconstructible {
+private:
+  Unconstructible(); // deleted
+};
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/Uncopyable.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 MaximInterfaceCore_Uncopyable
+#define MaximInterfaceCore_Uncopyable
+
+namespace MaximInterfaceCore {
+
+class Uncopyable {
+protected:
+  Uncopyable() {}
+  ~Uncopyable() {}
+
+private:
+  Uncopyable(const Uncopyable &); // deleted
+  const Uncopyable & operator=(const Uncopyable &); // deleted
+};
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/WriteMessage.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 MaximInterfaceCore_WriteMessage
+#define MaximInterfaceCore_WriteMessage
+
+#include <string>
+#include "Function.hpp"
+
+namespace MaximInterfaceCore {
+
+/// Writes a message string to an output.
+typedef Function<void(const std::string &)> WriteMessage;
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/array.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,191 @@
+/*******************************************************************************
+* 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 MaximInterfaceCore_array
+#define MaximInterfaceCore_array
+
+#include <stddef.h>
+#include <stdint.h>
+#include <algorithm>
+#include <iterator>
+
+namespace MaximInterfaceCore {
+
+/// 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;
+
+  /// @name 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 data()[pos]; }
+
+  reference front() {
+    return const_cast<reference>(static_cast<const array &>(*this).front());
+  }
+
+  const_reference front() const { return operator[](0); }
+
+  reference back() {
+    return const_cast<reference>(static_cast<const array &>(*this).back());
+  }
+
+  const_reference back() const { return operator[](size() - 1); }
+
+  pointer data() {
+    return const_cast<pointer>(static_cast<const array &>(*this).data());
+  }
+
+  const_pointer data() const { return _buffer; }
+
+  /// @}
+
+  /// @name Iterators
+  /// @{
+
+  iterator begin() {
+    return const_cast<iterator>(static_cast<const array &>(*this).cbegin());
+  }
+
+  const_iterator begin() const { return cbegin(); }
+
+  const_iterator cbegin() const { return data(); }
+
+  iterator end() {
+    return const_cast<iterator>(static_cast<const array &>(*this).cend());
+  }
+
+  const_iterator end() const { return cend(); }
+
+  const_iterator cend() const { return cbegin() + 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(); }
+
+  /// @}
+
+  /// @name Capacity
+  /// @{
+
+  static bool empty() { return size() == 0; }
+
+  static size_type size() { return N; }
+
+  static size_type max_size() { return size(); }
+
+  /// Alternative to size() when a constant expression is required.
+  static const size_type csize = N;
+
+  /// @}
+
+  /// @name Operations
+  /// @{
+
+  void fill(const_reference value) { std::fill(begin(), end(), value); }
+
+  void swap(array & other) { std::swap_ranges(begin(), end(), other.begin()); }
+
+  /// @}
+
+  /// @private
+  /// @note Implementation detail set public to allow aggregate initialization.
+  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 MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/array_span.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,61 @@
+/*******************************************************************************
+* Copyright (C) 2018 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 MaximInterfaceCore_array_span
+#define MaximInterfaceCore_array_span
+
+#include "array.hpp"
+#include "span.hpp"
+#include "type_traits.hpp"
+#include "Unconstructible.hpp"
+
+namespace MaximInterfaceCore {
+
+/// @brief
+/// Defines a standard set of types for data fields that are represented as a
+/// fixed-size array of elements.
+/// @tparam T A const qualifier is not allowed.
+template <typename T, size_t N> struct array_span : Unconstructible {
+  typedef typename remove_volatile<T>::type element;
+  static const size_t size = N;
+
+  typedef MaximInterfaceCore::array<element, N> array;
+  typedef MaximInterfaceCore::span<const T, N> const_span;
+  typedef MaximInterfaceCore::span<T, N> span;
+};
+
+// Specialization for "const T" is not defined.
+template <typename T, size_t N> struct array_span<const T, N>;
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/crc.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,81 @@
+/*******************************************************************************
+* 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 MaximInterfaceCore {
+
+uint_fast8_t calculateCrc8(uint_fast8_t crc, uint_fast8_t data) {
+  // See Application Note 27
+  crc = (crc ^ data) & 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(uint_fast8_t crc, span<const uint_least8_t> data) {
+  for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) {
+    crc = calculateCrc8(crc, data[i]);
+  }
+  return crc;
+}
+
+uint_fast16_t calculateCrc16(uint_fast16_t crc, uint_fast8_t data) {
+  static 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 ^= 0xC001u;
+  }
+  data16 <<= 6;
+  crc ^= data16;
+  data16 <<= 1;
+  crc ^= data16;
+  return crc;
+}
+
+uint_fast16_t calculateCrc16(uint_fast16_t crc,
+                             span<const uint_least8_t> data) {
+  for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) {
+    crc = calculateCrc16(crc, data[i]);
+  }
+  return crc;
+}
+
+} // namespace MaximInterfaceCore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/crc.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,107 @@
+/*******************************************************************************
+* 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 MaximInterfaceCore_crc
+#define MaximInterfaceCore_crc
+
+#include <stddef.h>
+#include <stdint.h>
+#include "Config.hpp"
+#include "span.hpp"
+
+namespace MaximInterfaceCore {
+
+/// @brief Perform a CRC8 calculation.
+/// @param crc Beginning state of the CRC generator.
+/// @param data Data to pass though the CRC generator.
+/// @returns The calculated CRC8.
+MaximInterfaceCore_EXPORT uint_fast8_t calculateCrc8(uint_fast8_t crc,
+                                                     uint_fast8_t data);
+
+/// @brief
+/// Perform a CRC8 calculation with the CRC generator initialized to zero.
+/// @param data Data to pass though the CRC generator.
+/// @returns The calculated CRC8.
+inline uint_fast8_t calculateCrc8(uint_fast8_t data) {
+  return calculateCrc8(0, data);
+}
+
+/// @brief Perform a CRC8 calculation with variable length data.
+/// @param crc Beginning state of the CRC generator.
+/// @param[in] data Data array to pass through the CRC generator.
+/// @returns The calculated CRC8.
+MaximInterfaceCore_EXPORT uint_fast8_t
+calculateCrc8(uint_fast8_t crc, span<const uint_least8_t> data);
+
+/// @brief
+/// Perform a CRC8 calculation with variable length data and the CRC generator
+/// initialized to zero.
+/// @param[in] data Data array to pass through the CRC generator.
+/// @returns The calculated CRC8.
+inline uint_fast8_t calculateCrc8(span<const uint_least8_t> data) {
+  return calculateCrc8(0, data);
+}
+
+/// @brief Perform a CRC16 calculation.
+/// @param crc Beginning state of the CRC generator.
+/// @param data Data to pass though the CRC generator.
+/// @returns The calculated CRC16.
+MaximInterfaceCore_EXPORT uint_fast16_t calculateCrc16(uint_fast16_t crc,
+                                                       uint_fast8_t data);
+
+/// @brief
+/// Perform a CRC16 calculation with the CRC generator initialized to zero.
+/// @param data Data to pass though the CRC generator.
+/// @returns The calculated CRC16.
+inline uint_fast16_t calculateCrc16(uint_fast8_t data) {
+  return calculateCrc16(0, data);
+}
+
+/// @brief Perform a CRC16 calculation with variable length data.
+/// @param crc Beginning state of the CRC generator.
+/// @param[in] data Data array to pass through the CRC generator.
+/// @returns The calculated CRC16.
+MaximInterfaceCore_EXPORT uint_fast16_t
+calculateCrc16(uint_fast16_t crc, span<const uint_least8_t> data);
+
+/// @brief
+/// Perform a CRC16 calculation with variable length data and the CRC generator
+/// initialized to zero.
+/// @param[in] data Data array to pass through the CRC generator.
+/// @returns The calculated CRC16.
+inline uint_fast16_t calculateCrc16(span<const uint_least8_t> data) {
+  return calculateCrc16(0, data);
+}
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/span.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,370 @@
+/*******************************************************************************
+* Copyright (C) 2018 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 MaximInterfaceCore_span
+#define MaximInterfaceCore_span
+
+#include <stddef.h>
+#include <stdint.h>
+#include <iterator>
+#include <vector>
+#include "array.hpp"
+#include "type_traits.hpp"
+
+namespace MaximInterfaceCore {
+
+/// Differentiates spans of static and dynamic extent.
+static const size_t dynamic_extent = SIZE_MAX;
+
+/// @brief
+/// Generic memory span class similar to gsl::span and the proposed std::span.
+/// @note
+/// Separate implementations are used for spans of static and dynamic extent.
+template <typename T, size_t Extent = dynamic_extent> class span;
+
+namespace detail {
+
+// Implementation of common span functionality using CRTP.
+template <template <typename, size_t = MaximInterfaceCore::dynamic_extent>
+          class span,
+          typename T, size_t Extent>
+class span_base {
+public:
+  typedef T element_type;
+  typedef typename remove_cv<element_type>::type value_type;
+  typedef size_t index_type;
+  typedef ptrdiff_t difference_type;
+  typedef element_type * pointer;
+  typedef const element_type * const_pointer;
+  typedef element_type & reference;
+  typedef const element_type & const_reference;
+  typedef element_type * iterator;
+  typedef const element_type * const_iterator;
+  typedef std::reverse_iterator<iterator> reverse_iterator;
+  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+  static const index_type extent = Extent;
+
+protected:
+  span_base(pointer data) : data_(data) {}
+  ~span_base() {}
+
+public:
+  /// @name Iterators
+  /// @{
+
+  iterator begin() const {
+    return const_cast<iterator>(static_cast<const span_base &>(*this).cbegin());
+  }
+
+  const_iterator cbegin() const { return data(); }
+
+  iterator end() const {
+    return const_cast<iterator>(static_cast<const span_base &>(*this).cend());
+  }
+
+  const_iterator cend() const { return cbegin() + size(); }
+
+  reverse_iterator rbegin() const { return reverse_iterator(end()); }
+
+  const_reverse_iterator crbegin() const {
+    return const_reverse_iterator(cend());
+  }
+
+  reverse_iterator rend() const { return reverse_iterator(begin()); }
+
+  const_reverse_iterator crend() const {
+    return const_reverse_iterator(cbegin());
+  }
+
+  /// @}
+
+  /// @name Element access
+  /// @{
+
+  reference front() const { return operator[](0); }
+
+  reference back() const { return operator[](size() - 1); }
+
+  reference operator[](index_type idx) const { return data()[idx]; }
+
+  pointer data() const { return data_; }
+
+  /// @}
+
+  /// @name Subviews
+  /// @{
+
+  template <index_type Count> span<element_type, Count> first() const {
+    return subspan<0, Count>();
+  }
+
+  span<element_type> first(index_type Count) const { return subspan(0, Count); }
+
+  span<element_type> last(index_type Count) const {
+    return subspan(size() - Count, Count);
+  }
+
+  template <index_type Offset, index_type Count>
+  span<element_type, Count> subspan() const {
+    return span<element_type, Count>(data() + Offset, Count);
+  }
+
+  span<element_type> subspan(index_type Offset,
+                             index_type Count = dynamic_extent) const {
+    return span<element_type>(
+        data() + Offset, Count == dynamic_extent ? size() - Offset : Count);
+  }
+
+  /// @}
+
+private:
+  index_type size() const {
+    return static_cast<const span<T, Extent> &>(*this).size();
+  }
+
+  pointer data_;
+};
+
+template <typename T> struct is_array : false_type {};
+
+template <typename T> struct is_array<T[]> : true_type {};
+
+template <typename T, size_t N> struct is_array<T[N]> : true_type {};
+
+template <typename T> struct is_array_class_helper : false_type {};
+
+template <typename T, size_t N>
+struct is_array_class_helper<array<T, N> > : true_type {};
+
+template <typename T>
+struct is_array_class : is_array_class_helper<typename remove_cv<T>::type> {};
+
+template <typename T> struct is_span_helper : false_type {};
+
+template <typename T, size_t Extent>
+struct is_span_helper<span<T, Extent> > : true_type {};
+
+template <typename T>
+struct is_span : is_span_helper<typename remove_cv<T>::type> {};
+
+template <typename T> struct is_vector_helper : false_type {};
+
+template <typename T, typename Allocator>
+struct is_vector_helper<std::vector<T, Allocator> > : true_type {};
+
+template <typename T>
+struct is_vector : is_vector_helper<typename remove_cv<T>::type> {};
+
+// Used by the static extent span to disable the container constructors.
+template <typename T>
+struct enable_if_static_extent_convertible
+    : enable_if<!(is_array<T>::value || is_array_class<T>::value ||
+                  is_span<T>::value || is_vector<T>::value)> {};
+
+// Used by the dynamic extent span to disable the container constructors.
+template <typename T>
+struct enable_if_dynamic_extent_convertible
+    : enable_if<!(is_array<T>::value || is_span<T>::value ||
+                  is_vector<T>::value)> {};
+
+} // namespace detail
+
+// Implementation of the static extent span.
+template <typename T, size_t Extent>
+class span : public detail::span_base<MaximInterfaceCore::span, T, Extent> {
+  typedef detail::span_base<MaximInterfaceCore::span, T, Extent> span_base;
+
+public:
+  using span_base::extent;
+  using typename span_base::element_type;
+  using typename span_base::index_type;
+  using typename span_base::pointer;
+  using typename span_base::value_type;
+
+  span(pointer data, index_type) : span_base(data) {}
+
+  span(pointer begin, pointer) : span_base(begin) {}
+
+  span(element_type (&arr)[extent]) : span_base(arr) {}
+
+  span(array<value_type, extent> & arr) : span_base(arr.data()) {}
+
+  span(const array<value_type, extent> & arr) : span_base(arr.data()) {}
+
+  template <typename U> span(const span<U, extent> & s) : span_base(s.data()) {}
+
+  template <typename Allocator>
+  span(std::vector<value_type, Allocator> & vec) : span_base(&vec.front()) {}
+
+  template <typename Allocator>
+  span(const std::vector<value_type, Allocator> & vec)
+      : span_base(&vec.front()) {}
+
+  template <typename Container>
+  span(Container & cont,
+       typename detail::enable_if_static_extent_convertible<Container>::type * =
+           NULL)
+      : span_base(cont.data()) {}
+
+  template <typename Container>
+  span(const Container & cont,
+       typename detail::enable_if_static_extent_convertible<Container>::type * =
+           NULL)
+      : span_base(cont.data()) {}
+
+  /// @name Observers
+  /// @{
+
+  static index_type size() { return extent; }
+
+  static index_type size_bytes() { return size() * sizeof(element_type); }
+
+  static bool empty() { return size() == 0; }
+
+  /// @}
+
+  /// @name Subviews
+  /// @{
+
+  template <index_type Count> span<element_type, Count> last() const {
+    return this->template subspan<extent - Count, Count>();
+  }
+
+  /// @}
+};
+
+// Implementation of the dynamic extent span.
+template <typename T>
+class span<T, dynamic_extent>
+    : public detail::span_base<MaximInterfaceCore::span, T, dynamic_extent> {
+  typedef detail::span_base<MaximInterfaceCore::span, T, dynamic_extent>
+      span_base;
+
+public:
+  using typename span_base::element_type;
+  using typename span_base::index_type;
+  using typename span_base::pointer;
+  using typename span_base::value_type;
+
+  span() : span_base(NULL), size_(0) {}
+
+  span(pointer data, index_type size) : span_base(data), size_(size) {}
+
+  span(pointer begin, pointer end) : span_base(begin), size_(end - begin) {}
+
+  template <size_t N> span(element_type (&arr)[N]) : span_base(arr), size_(N) {}
+
+  template <typename U, size_t N>
+  span(const span<U, N> & s) : span_base(s.data()), size_(s.size()) {}
+
+  template <typename Allocator>
+  span(std::vector<value_type, Allocator> & vec)
+      : span_base(vec.empty() ? NULL : &vec.front()), size_(vec.size()) {}
+
+  template <typename Allocator>
+  span(const std::vector<value_type, Allocator> & vec)
+      : span_base(vec.empty() ? NULL : &vec.front()), size_(vec.size()) {}
+
+  template <typename Container>
+  span(
+      Container & cont,
+      typename detail::enable_if_dynamic_extent_convertible<Container>::type * =
+          NULL)
+      : span_base(cont.data()), size_(cont.size()) {}
+
+  template <typename Container>
+  span(
+      const Container & cont,
+      typename detail::enable_if_dynamic_extent_convertible<Container>::type * =
+          NULL)
+      : span_base(cont.data()), size_(cont.size()) {}
+
+  /// @name Observers
+  /// @{
+
+  index_type size() const { return size_; }
+
+  index_type size_bytes() const { return size() * sizeof(element_type); }
+
+  bool empty() const { return size() == 0; }
+
+  /// @}
+
+  /// @name Subviews
+  /// @{
+
+  template <index_type Count> span<element_type, Count> last() const {
+    return span<element_type, Count>(this->data() + (size() - Count), Count);
+  }
+
+  /// @}
+
+private:
+  index_type size_;
+};
+
+template <typename T>
+span<T> make_span(T * data, typename span<T>::index_type size) {
+  return span<T>(data, size);
+}
+
+template <typename T> span<T> make_span(T * begin, T * end) {
+  return span<T>(begin, end);
+}
+
+template <typename T, size_t N> span<T, N> make_span(T (&arr)[N]) {
+  return span<T, N>(arr);
+}
+
+template <typename T, size_t N> span<T, N> make_span(array<T, N> & arr) {
+  return arr;
+}
+
+template <typename T, size_t N>
+span<const T, N> make_span(const array<T, N> & arr) {
+  return arr;
+}
+
+template <typename Container>
+span<typename Container::value_type> make_span(Container & cont) {
+  return cont;
+}
+
+template <typename Container>
+span<const typename Container::value_type> make_span(const Container & cont) {
+  return cont;
+}
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/system_error.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,96 @@
+/*******************************************************************************
+* 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 MaximInterfaceCore {
+
+using std::string;
+
+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 string message(int condition) const {
+      return defaultErrorMessage(condition);
+    }
+  } instance;
+  return instance;
+}
+
+static string formatWhat(const error_code & ec) {
+  return string(ec.category().name()) + ' ' + ec.message();
+}
+
+template <typename T>
+static string formatWhat(const error_code & ec, const T & what_arg) {
+  return string(what_arg) + ": " + formatWhat(ec);
+}
+
+system_error::system_error(const error_code & ec)
+    : runtime_error(formatWhat(ec)), code_(ec) {}
+
+system_error::system_error(const error_code & ec, const string & what_arg)
+    : runtime_error(formatWhat(ec, what_arg)), code_(ec) {}
+
+system_error::system_error(const error_code & ec, const char * what_arg)
+    : runtime_error(formatWhat(ec, what_arg)), code_(ec) {}
+
+system_error::system_error(int ev, const error_category & ecat)
+    : runtime_error(formatWhat(error_code(ev, ecat))), code_(ev, ecat) {}
+
+system_error::system_error(int ev, const error_category & ecat,
+                           const string & what_arg)
+    : runtime_error(formatWhat(error_code(ev, ecat), what_arg)),
+      code_(ev, ecat) {}
+
+system_error::system_error(int ev, const error_category & ecat,
+                           const char * what_arg)
+    : runtime_error(formatWhat(error_code(ev, ecat), what_arg)),
+      code_(ev, ecat) {}
+
+} // namespace MaximInterfaceCore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/system_error.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,227 @@
+/*******************************************************************************
+* 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
+/// @brief
+/// Error handling constructs similar to std::error_code, std::error_condition,
+/// and std::error_category.
+
+#ifndef MaximInterfaceCore_system_error
+#define MaximInterfaceCore_system_error
+
+#include <stdexcept>
+#include <string>
+#include "Config.hpp"
+#include "SafeBool.hpp"
+#include "Uncopyable.hpp"
+
+namespace MaximInterfaceCore {
+
+class error_condition;
+class error_code;
+
+class error_category : private Uncopyable {
+public:
+  virtual ~error_category() {}
+
+  virtual const char * name() const = 0;
+
+  MaximInterfaceCore_EXPORT virtual error_condition
+  default_error_condition(int code) const;
+
+  MaximInterfaceCore_EXPORT virtual bool
+  equivalent(int code, const error_condition & condition) const;
+
+  MaximInterfaceCore_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;
+}
+
+MaximInterfaceCore_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 SafeBool() const { return makeSafeBool(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 SafeBool() const { return makeSafeBool(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);
+}
+
+class system_error : public std::runtime_error {
+public:
+  MaximInterfaceCore_EXPORT system_error(const error_code & ec);
+
+  MaximInterfaceCore_EXPORT system_error(const error_code & ec,
+                                         const std::string & what_arg);
+
+  MaximInterfaceCore_EXPORT system_error(const error_code & ec,
+                                         const char * what_arg);
+
+  MaximInterfaceCore_EXPORT system_error(int ev, const error_category & ecat);
+
+  MaximInterfaceCore_EXPORT system_error(int ev, const error_category & ecat,
+                                         const std::string & what_arg);
+
+  MaximInterfaceCore_EXPORT system_error(int ev, const error_category & ecat,
+                                         const char * what_arg);
+
+  const error_code & code() const { return code_; }
+
+private:
+  error_code code_;
+};
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/type_traits.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,88 @@
+/*******************************************************************************
+* 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 MaximInterfaceCore_type_traits
+#define MaximInterfaceCore_type_traits
+
+namespace MaximInterfaceCore {
+
+template <typename T, T v> struct integral_constant {
+  static const T value = v;
+  typedef T value_type;
+  typedef integral_constant<T, v> type;
+  operator value_type() const { return value; }
+  value_type operator()() const { return value; }
+};
+
+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)> {};
+
+template <typename T> struct remove_const { typedef T type; };
+template <typename T> struct remove_const<const T> { typedef T type; };
+
+template <typename T> struct remove_volatile { typedef T type; };
+template <typename T> struct remove_volatile<volatile T> { typedef T type; };
+
+template <typename T> struct remove_cv {
+  typedef typename remove_volatile<typename remove_const<T>::type>::type type;
+};
+
+} // namespace MaximInterfaceCore
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/Config.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,37 @@
+/*******************************************************************************
+* Copyright (C) 2019 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 MaximInterfaceDevices_EXPORT
+  #define MaximInterfaceDevices_EXPORT
+#endif
+
+namespace MaximInterfaceDevices { namespace Core = MaximInterfaceCore; }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS18B20.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,253 @@
+/*******************************************************************************
+* 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 <MaximInterfaceCore/Error.hpp>
+#include <MaximInterfaceCore/OneWireMaster.hpp>
+#include "DS18B20.hpp"
+
+namespace MaximInterfaceDevices {
+
+using namespace Core;
+
+const uint_least8_t DS18B20::nineBitResolution;
+const uint_least8_t DS18B20::tenBitResolution;
+const uint_least8_t DS18B20::elevenBitResolution;
+const uint_least8_t DS18B20::twelveBitResolution;
+
+error_code DS18B20::initialize() {
+  Scratchpad::array 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[] = {0x4E, th, tl, res};
+    result = master->writeBlock(sendBlock);
+    if (!result) {
+      resolution = res;
+    }
+  }
+  return result;
+}
+
+error_code DS18B20::readScratchpad(Scratchpad::span scratchpad) {
+  error_code result = selectRom(*master);
+  if (result) {
+    return result;
+  }
+  result = master->writeByte(0xBE);
+  if (result) {
+    return result;
+  }
+  result = master->readBlock(scratchpad);
+  if (result) {
+    return result;
+  }
+  uint_least8_t receivedCrc;
+  result = master->readByte(receivedCrc);
+  if (result) {
+    return result;
+  }
+  if (receivedCrc == calculateCrc8(scratchpad)) {
+    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->writeByte(0xB4);
+  if (result) {
+    return result;
+  }
+  result = master->touchBit(localPower);
+  return result;
+}
+
+error_code DS18B20::copyScratchpad() {
+  const uint_least8_t copyScratchpadCmd = 0x48;
+
+  bool hasLocalPower;
+  error_code result = readPowerSupply(hasLocalPower);
+  if (result) {
+    return result;
+  }
+  result = selectRom(*master);
+  if (result) {
+    return result;
+  }
+  if (hasLocalPower) {
+    result = master->writeByte(copyScratchpadCmd);
+    bool recvbit = 0;
+    while (!recvbit && !result) {
+      result = master->touchBit(recvbit);
+    }
+  } else {
+    result = master->writeByteSetLevel(copyScratchpadCmd,
+                                       OneWireMaster::StrongLevel);
+    if (!result) {
+      sleep->invoke(10);
+      result = master->setLevel(OneWireMaster::NormalLevel);
+    }
+  }
+  return result;
+}
+
+error_code DS18B20::convertTemperature() {
+  const uint_least8_t convertTemperatureCmd = 0x44;
+
+  bool hasLocalPower;
+  error_code result = readPowerSupply(hasLocalPower);
+  if (result) {
+    return result;
+  }
+  result = selectRom(*master);
+  if (result) {
+    return result;
+  }
+  if (hasLocalPower) {
+    result = master->writeByte(convertTemperatureCmd);
+    bool recvbit = 0;
+    while (!result && !recvbit) {
+      result = master->touchBit(recvbit);
+    }
+  } else {
+    result = master->writeByteSetLevel(convertTemperatureCmd,
+                                       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->invoke(sleepTime);
+      result = master->setLevel(OneWireMaster::NormalLevel);
+    }
+  }
+  return result;
+}
+
+error_code DS18B20::recallEeprom() {
+  error_code result = selectRom(*master);
+  if (!result) {
+    result = master->writeByte(0xB8);
+  }
+  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::array scratchpad;
+  result = ds18b20.readScratchpad(scratchpad);
+  if (result) {
+    return result;
+  }
+
+  const 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 MaximInterfaceDevices
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS18B20.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,142 @@
+/*******************************************************************************
+* 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 MaximInterfaceDevices_DS18B20
+#define MaximInterfaceDevices_DS18B20
+
+#include <MaximInterfaceCore/array_span.hpp>
+#include <MaximInterfaceCore/SelectRom.hpp>
+#include <MaximInterfaceCore/Sleep.hpp>
+#include "Config.hpp"
+
+namespace MaximInterfaceDevices {
+
+/// @brief 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 Core::array_span<uint_least8_t, 8> Scratchpad;
+
+  DS18B20(Core::Sleep & sleep, Core::OneWireMaster & master,
+          const Core::SelectRom & selectRom)
+      : selectRom(selectRom), master(&master), sleep(&sleep), resolution(0) {}
+
+  void setSleep(Core::Sleep & sleep) { this->sleep = &sleep; }
+
+  void setMaster(Core::OneWireMaster & master) { this->master = &master; }
+
+  void setSelectRom(const Core::SelectRom & selectRom) {
+    this->selectRom = selectRom;
+  }
+
+  /// Initializes the device for first time use.
+  MaximInterfaceDevices_EXPORT Core::error_code initialize();
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeScratchpad(uint_least8_t th, uint_least8_t tl, uint_least8_t res);
+
+  /// @brief Read Scratchpad Command
+  /// @param[out] scratchpad Contents of scratchpad.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readScratchpad(Scratchpad::span scratchpad);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code copyScratchpad();
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readPowerSupply(bool & localPower);
+
+  /// @brief Convert Temperature Command
+  /// @details This command begins a temperature conversion.
+  MaximInterfaceDevices_EXPORT Core::error_code convertTemperature();
+
+  /// @brief Recall Command
+  /// @details This command recalls the temperature trigger values
+  /// and resolution stored in EEPROM to the scratchpad.
+  MaximInterfaceDevices_EXPORT Core::error_code recallEeprom();
+
+  MaximInterfaceDevices_EXPORT static const Core::error_category &
+  errorCategory();
+
+private:
+  Core::SelectRom selectRom;
+  Core::OneWireMaster * master;
+  const Core::Sleep * sleep;
+  uint_least8_t resolution;
+};
+
+/// @brief Reads the current temperature as an integer value with decimal.
+/// @param ds18b20 Device to read.
+/// @param[out] temperature Temperature in degrees Celsius multiplied by 16.
+MaximInterfaceDevices_EXPORT Core::error_code
+readTemperature(DS18B20 & ds18b20, int & temperature);
+
+inline Core::error_code make_error_code(DS18B20::ErrorValue e) {
+  return Core::error_code(e, DS18B20::errorCategory());
+}
+
+} // namespace MaximInterfaceDevices
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS1920.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 <MaximInterfaceCore/Error.hpp>
+#include <MaximInterfaceCore/OneWireMaster.hpp>
+#include "DS1920.hpp"
+
+namespace MaximInterfaceDevices {
+
+using namespace Core;
+
+error_code DS1920::writeScratchpad(uint_least8_t th, uint_least8_t tl) {
+  error_code result = selectRom(*master);
+  if (!result) {
+    const uint_least8_t sendBlock[] = {0x4E, th, tl};
+    result = master->writeBlock(sendBlock);
+  }
+  return result;
+}
+
+error_code DS1920::readScratchpad(Scratchpad::span scratchpad) {
+  error_code result = selectRom(*master);
+  if (!result) {
+    result = master->writeByte(0xBE);
+    if (!result) {
+      result = master->readBlock(scratchpad);
+      if (!result) {
+        uint_least8_t receivedCrc;
+        result = master->readByte(receivedCrc);
+        if (!result && (receivedCrc != calculateCrc8(scratchpad))) {
+          result = make_error_code(CrcError);
+        }
+      }
+    }
+  }
+  return result;
+}
+
+error_code DS1920::copyScratchpad() {
+  error_code result = selectRom(*master);
+  if (!result) {
+    result = master->writeByteSetLevel(0x48, OneWireMaster::StrongLevel);
+    if (!result) {
+      sleep->invoke(10);
+      result = master->setLevel(OneWireMaster::NormalLevel);
+    }
+  }
+  return result;
+}
+
+error_code DS1920::convertTemperature() {
+  error_code result = selectRom(*master);
+  if (!result) {
+    result = master->writeByteSetLevel(0x44, OneWireMaster::StrongLevel);
+    if (!result) {
+      sleep->invoke(750);
+      result = master->setLevel(OneWireMaster::NormalLevel);
+    }
+  }
+  return result;
+}
+
+error_code DS1920::recallEeprom() {
+  error_code result = selectRom(*master);
+  if (!result) {
+    result = master->writeByte(0xB8);
+  }
+  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::array 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 MaximInterfaceDevices
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS1920.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,124 @@
+/*******************************************************************************
+* 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 MaximInterfaceDevices_DS1920
+#define MaximInterfaceDevices_DS1920
+
+#include <MaximInterfaceCore/array_span.hpp>
+#include <MaximInterfaceCore/SelectRom.hpp>
+#include <MaximInterfaceCore/Sleep.hpp>
+#include "Config.hpp"
+
+namespace MaximInterfaceDevices {
+
+/// @brief 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 Core::array_span<uint_least8_t, 8> Scratchpad;
+
+  DS1920(Core::Sleep & sleep, Core::OneWireMaster & master,
+         const Core::SelectRom & selectRom)
+      : selectRom(selectRom), master(&master), sleep(&sleep) {}
+
+  void setSleep(Core::Sleep & sleep) { this->sleep = &sleep; }
+
+  void setMaster(Core::OneWireMaster & master) { this->master = &master; }
+
+  void setSelectRom(const Core::SelectRom & selectRom) {
+    this->selectRom = selectRom;
+  }
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeScratchpad(uint_least8_t th, uint_least8_t tl);
+
+  /// @brief Read Scratchpad Command
+  /// @param[out] scratchpad Contents of scratchpad.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readScratchpad(Scratchpad::span scratchpad);
+
+  /// @brief Copy Scratchpad Command
+  /// @details This command copies from the scratchpad into the
+  /// EEPROM of the DS1920, storing the temperature trigger bytes
+  /// in nonvolatile memory.
+  MaximInterfaceDevices_EXPORT Core::error_code copyScratchpad();
+
+  /// @brief Convert Temperature Command
+  /// @details This command begins a temperature conversion.
+  MaximInterfaceDevices_EXPORT Core::error_code convertTemperature();
+
+  /// @brief Recall Command
+  /// @details This command recalls the temperature trigger values
+  /// stored in EEPROM to the scratchpad.
+  MaximInterfaceDevices_EXPORT Core::error_code recallEeprom();
+
+  MaximInterfaceDevices_EXPORT static const Core::error_category &
+  errorCategory();
+
+private:
+  Core::SelectRom selectRom;
+  Core::OneWireMaster * master;
+  const Core::Sleep * sleep;
+};
+
+/// @brief Reads the current temperature as an integer value.
+/// @param ds1920 Device to read.
+/// @param[out] temperature Temperature in degrees Celsius multiplied by 2.
+MaximInterfaceDevices_EXPORT Core::error_code
+readTemperature(DS1920 & ds1920, int & temperature);
+
+inline Core::error_code make_error_code(DS1920::ErrorValue e) {
+  return Core::error_code(e, DS1920::errorCategory());
+}
+
+} // namespace MaximInterfaceDevices
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS2413.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,126 @@
+/*******************************************************************************
+* 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 <MaximInterfaceCore/Error.hpp>
+#include <MaximInterfaceCore/OneWireMaster.hpp>
+#include "DS2413.hpp"
+
+namespace MaximInterfaceDevices {
+
+using namespace Core;
+
+error_code DS2413::readStatus(Status & status) const {
+  uint_least8_t val;
+  const error_code result = pioAccessRead(val);
+  if (!result) {
+    status = val;
+  }
+  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);
+    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";
+      }
+      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[DS2413::PioAOutputState]) {
+    result =
+        ds2413.writeOutputState(pioAState, status[DS2413::PioBOutputState]);
+  }
+  return result;
+}
+
+error_code writePioBOutputState(DS2413 & ds2413, bool pioBState) {
+  DS2413::Status status;
+  error_code result = ds2413.readStatus(status);
+  if (!result && pioBState != status[DS2413::PioBOutputState]) {
+    result =
+        ds2413.writeOutputState(status[DS2413::PioAOutputState], pioBState);
+  }
+  return result;
+}
+
+} // namespace MaximInterfaceDevices
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS2413.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,107 @@
+/*******************************************************************************
+* 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 MaximInterfaceDevices_DS2413
+#define MaximInterfaceDevices_DS2413
+
+#include <stdint.h>
+#include <MaximInterfaceCore/FlagSet.hpp>
+#include <MaximInterfaceCore/SelectRom.hpp>
+#include "Config.hpp"
+
+namespace MaximInterfaceDevices {
+
+/// @brief 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 };
+
+  enum StatusFlags {
+    PioAInputState = 0x1,
+    PioAOutputState = 0x2,
+    PioBInputState = 0x4,
+    PioBOutputState = 0x8
+  };
+  typedef Core::FlagSet<StatusFlags, 4> Status;
+
+  DS2413(Core::OneWireMaster & master, const Core::SelectRom & selectRom)
+      : selectRom(selectRom), master(&master) {}
+
+  void setMaster(Core::OneWireMaster & master) { this->master = &master; }
+
+  void setSelectRom(const Core::SelectRom & selectRom) {
+    this->selectRom = selectRom;
+  }
+
+  /// Read the input and output logic states for all PIO pins.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readStatus(Status & status) const;
+
+  /// Write the output logic states for all PIO pins.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeOutputState(bool pioAState, bool pioBState);
+
+  MaximInterfaceDevices_EXPORT static const Core::error_category &
+  errorCategory();
+
+private:
+  Core::error_code pioAccessRead(uint_least8_t & val) const;
+  Core::error_code pioAccessWrite(uint_least8_t val);
+
+  Core::SelectRom selectRom;
+  Core::OneWireMaster * master;
+};
+
+/// Write the output logic state for only PIOA.
+MaximInterfaceDevices_EXPORT Core::error_code
+writePioAOutputState(DS2413 & ds2413, bool pioAState);
+
+/// Write the output logic state for only PIOB.
+MaximInterfaceDevices_EXPORT Core::error_code
+writePioBOutputState(DS2413 & ds2413, bool pioBState);
+
+inline Core::error_code make_error_code(DS2413::ErrorValue e) {
+  return Core::error_code(e, DS2413::errorCategory());
+}
+
+} // namespace MaximInterfaceDevices
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS2431.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,178 @@
+/*******************************************************************************
+* 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 <MaximInterfaceCore/Error.hpp>
+#include <MaximInterfaceCore/OneWireMaster.hpp>
+#include "DS2431.hpp"
+
+namespace MaximInterfaceDevices {
+
+using namespace Core;
+
+error_code writeMemory(DS2431 & device, DS2431::Address targetAddress,
+                       DS2431::Scratchpad::const_span data) {
+  error_code result = device.writeScratchpad(targetAddress, data);
+  if (result) {
+    return result;
+  }
+  DS2431::Scratchpad::array 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,
+                              span<uint_least8_t> data) const {
+  error_code result = selectRom(*master);
+  if (result) {
+    return result;
+  }
+  const uint_least8_t sendBlock[] = {0xF0, beginAddress, 0x00};
+  result = master->writeBlock(sendBlock);
+  if (result) {
+    return result;
+  }
+  result = master->readBlock(data);
+  return result;
+}
+
+error_code DS2431::writeScratchpad(Address targetAddress,
+                                   Scratchpad::const_span data) {
+  error_code result = selectRom(*master);
+  if (result) {
+    return result;
+  }
+  uint_least8_t block[3 + Scratchpad::size] = {0x0F, targetAddress, 0x00};
+  std::copy(data.begin(), data.end(), block + 3);
+  result = master->writeBlock(block);
+  if (result) {
+    return result;
+  }
+  const uint_fast16_t calculatedCrc = calculateCrc16(block) ^ 0xFFFFu;
+  result = master->readBlock(make_span(block, 2));
+  if (result) {
+    return result;
+  }
+  if (calculatedCrc !=
+      ((static_cast<uint_fast16_t>(block[1]) << 8) | block[0])) {
+    result = make_error_code(CrcError);
+  }
+  return result;
+}
+
+error_code DS2431::readScratchpad(Scratchpad::span data,
+                                  uint_least8_t & esByte) {
+  typedef array<uint_least8_t, 6 + Scratchpad::size> Block;
+
+  error_code result = selectRom(*master);
+  if (result) {
+    return result;
+  }
+  Block block = {0xAA};
+  result = master->writeByte(block.front());
+  if (result) {
+    return result;
+  }
+  result = master->readBlock(make_span(block).subspan(1));
+  if (result) {
+    return result;
+  }
+  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(make_span(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 {
+    result = make_error_code(CrcError);
+  }
+  return result;
+}
+
+error_code DS2431::copyScratchpad(Address targetAddress, uint_least8_t esByte) {
+  error_code result = selectRom(*master);
+  if (result) {
+    return result;
+  }
+  uint_least8_t block[] = {0x55, targetAddress, 0x00};
+  result = master->writeBlock(block);
+  if (result) {
+    return result;
+  }
+  result = master->writeByteSetLevel(esByte, OneWireMaster::StrongLevel);
+  if (result) {
+    return result;
+  }
+  sleep->invoke(10);
+  result = master->setLevel(OneWireMaster::NormalLevel);
+  if (result) {
+    return result;
+  }
+  result = master->readByte(block[0]);
+  if (result) {
+    return result;
+  }
+  if (block[0] != 0xAA) {
+    result = make_error_code(OperationFailure);
+  }
+  return result;
+}
+
+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";
+      }
+      return defaultErrorMessage(condition);
+    }
+  } instance;
+  return instance;
+}
+
+} // namespace MaximInterfaceDevices
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS2431.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,126 @@
+/*******************************************************************************
+* 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 MaximInterfaceDevices_DS2431
+#define MaximInterfaceDevices_DS2431
+
+#include <MaximInterfaceCore/array_span.hpp>
+#include <MaximInterfaceCore/SelectRom.hpp>
+#include <MaximInterfaceCore/Sleep.hpp>
+#include "Config.hpp"
+
+namespace MaximInterfaceDevices {
+
+/// @brief 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 Core::array_span<uint_least8_t, 8> Scratchpad;
+  typedef uint_least8_t Address;
+
+  DS2431(Core::Sleep & sleep, Core::OneWireMaster & master,
+         const Core::SelectRom & selectRom)
+      : selectRom(selectRom), master(&master), sleep(&sleep) {}
+
+  void setSleep(Core::Sleep & sleep) { this->sleep = &sleep; }
+
+  void setMaster(Core::OneWireMaster & master) { this->master = &master; }
+
+  void setSelectRom(const Core::SelectRom & selectRom) {
+    this->selectRom = selectRom;
+  }
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readMemory(Address beginAddress, Core::span<uint_least8_t> data) const;
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeScratchpad(Address targetAddress, Scratchpad::const_span data);
+
+  /// @brief Reads contents of scratchpad.
+  /// @param[out] data Data read from scratchpad.
+  /// @param[out] esByte E/S byte read before scratchpad data.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readScratchpad(Scratchpad::span data, uint_least8_t & esByte);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  copyScratchpad(Address targetAddress, uint_least8_t esByte);
+
+  MaximInterfaceDevices_EXPORT static const Core::error_category &
+  errorCategory();
+
+private:
+  Core::SelectRom selectRom;
+  Core::OneWireMaster * master;
+  const Core::Sleep * sleep;
+};
+
+/// @brief
+/// Writes data to EEPROM using Write Scratchpad, Read Scratchpad,
+/// and Copy Scratchpad commands.
+/// @param device Device to write.
+/// @param[in] targetAddress EEPROM memory address to start writing at.
+/// @param[in] data Data to write to EEPROM.
+MaximInterfaceDevices_EXPORT Core::error_code
+writeMemory(DS2431 & device, DS2431::Address targetAddress,
+            DS2431::Scratchpad::const_span data);
+
+inline Core::error_code make_error_code(DS2431::ErrorValue e) {
+  return Core::error_code(e, DS2431::errorCategory());
+}
+
+} // namespace MaximInterfaceDevices
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS2465.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,782 @@
+/*******************************************************************************
+* 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 <MaximInterfaceCore/Error.hpp>
+#include "DS2465.hpp"
+
+namespace MaximInterfaceDevices {
+
+using namespace Core;
+
+/// 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;
+
+static const uint_least8_t scratchpad = 0x00;
+static const uint_least8_t commandReg = 0x60;
+
+static const uint_least8_t owTransmitBlockCmd = 0x69;
+
+/// 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 int maxBlockSize = 63;
+
+const int DS2465::memoryPages;
+const int DS2465::segmentsPerPage;
+
+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) {
+    const uint_least8_t command[] = {
+        0x1E, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
+                                              : 0xBF)};
+    result = writeMemory(commandReg, command);
+  }
+  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) {
+    const uint_least8_t command[] = {
+        0x2D, static_cast<uint_least8_t>((regwrite << 7) | (swap << 6) |
+                                         (pageNum << 4) | segmentNum)};
+    result = writeMemory(commandReg, command);
+    if (!result) {
+      sleep->invoke(shaComputationDelayMs);
+    }
+  }
+  return result;
+}
+
+error_code DS2465::computeAuthMac(bool swap, int pageNum,
+                                  PageRegion region) const {
+  error_code result = make_error_code(ArgumentOutOfRangeError);
+  if (pageNum >= 0) {
+    const uint_least8_t command[] = {
+        0x3C, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
+                                              : 0xBF)};
+    result = writeMemory(commandReg, command);
+    if (!result) {
+      sleep->invoke(shaComputationDelayMs * 2);
+    }
+  }
+  return result;
+}
+
+error_code DS2465::computeSlaveSecret(bool swap, int pageNum,
+                                      PageRegion region) {
+  error_code result = make_error_code(ArgumentOutOfRangeError);
+  if (pageNum >= 0) {
+    const uint_least8_t command[] = {
+        0x4B, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
+                                              : 0xBF)};
+    result = writeMemory(commandReg, command);
+    if (!result) {
+      sleep->invoke(shaComputationDelayMs * 2);
+    }
+  }
+  return result;
+}
+
+error_code DS2465::readPage(int pageNum, Page::span data) const {
+  uint_least8_t addr;
+  switch (pageNum) {
+  case 0:
+    addr = 0x80;
+    break;
+  case 1:
+    addr = 0xA0;
+    break;
+  default:
+    return make_error_code(ArgumentOutOfRangeError);
+  }
+  return readMemory(addr, data);
+}
+
+error_code DS2465::writePage(int pageNum, Page::const_span data) {
+  error_code result = writeMemory(scratchpad, data);
+  if (!result) {
+    result = copyScratchpad(false, pageNum, false, 0);
+  }
+  if (!result) {
+    sleep->invoke(eepromPageWriteDelayMs);
+  }
+  return result;
+}
+
+error_code DS2465::writeSegment(int pageNum, int segmentNum,
+                                Segment::const_span data) {
+  error_code result = writeMemory(scratchpad, data);
+  if (!result) {
+    result = copyScratchpad(false, pageNum, true, segmentNum);
+  }
+  if (!result) {
+    sleep->invoke(eepromSegmentWriteDelayMs);
+  }
+  return result;
+}
+
+error_code DS2465::writeMasterSecret(Page::const_span masterSecret) {
+  error_code result = writeMemory(scratchpad, masterSecret);
+  if (!result) {
+    result = copyScratchpad(true, 0, false, 0);
+  }
+  if (!result) {
+    sleep->invoke(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) {
+    const uint_least8_t command[] = {
+        0x5A,
+        static_cast<uint_least8_t>(destSecret ? 0
+                                              : (0x80 | (pageNum << 4) |
+                                                 (notFull << 3) | segmentNum))};
+    result = writeMemory(commandReg, command);
+  }
+  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
+  return writeConfig(Config(curConfig).setSPU(level == StrongLevel));
+}
+
+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
+  return writeConfig(Config(curConfig).set1WS(newSpeed == OverdriveSpeed));
+}
+
+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[] = {
+      0x78, static_cast<uint_least8_t>(data.writeBit ? 0x80 : 0x00)};
+  error_code result = writeMemory(commandReg, command);
+  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(span<uint_least8_t> recvBuf) {
+  // 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;
+  span<uint_least8_t>::index_type recvIdx = 0;
+  while (recvIdx < recvBuf.size() && !result) {
+    const uint_least8_t command[] = {
+        0xE1,
+        static_cast<uint_least8_t>(std::min<span<uint_least8_t>::index_type>(
+            recvBuf.size() - recvIdx, maxBlockSize))};
+    result = writeMemory(commandReg, command);
+    if (!result) {
+      result = pollBusy();
+    }
+    if (!result) {
+      result = readMemory(scratchpad, recvBuf.subspan(recvIdx, command[1]));
+    }
+    recvIdx += command[1];
+  }
+  return result;
+}
+
+error_code DS2465::writeBlock(span<const uint_least8_t> sendBuf) {
+  error_code result;
+  span<const uint_least8_t>::index_type sendIdx = 0;
+  while (sendIdx < sendBuf.size() && !result) {
+    const uint_least8_t command[] = {
+        owTransmitBlockCmd, static_cast<uint_least8_t>(
+                                std::min<span<const uint_least8_t>::index_type>(
+                                    sendBuf.size() - sendIdx, maxBlockSize))};
+
+    // prefill scratchpad with required data
+    result = writeMemory(scratchpad, sendBuf.subspan(sendIdx, 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);
+    }
+    if (!result) {
+      result = pollBusy();
+    }
+    sendIdx += 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);
+  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;
+  }
+
+  const uint_least8_t command = 0x96;
+  result = writeMemory(commandReg, make_span(&command, 1));
+  if (result) {
+    return result;
+  }
+
+  result = pollBusy();
+  if (result) {
+    return result;
+  }
+
+  result = readMemory(0x62, make_span(&recvByte, 1));
+  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[] = {0xA5, sendByte};
+  result = writeMemory(commandReg, command);
+  if (result) {
+    return 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[] = {
+      0x87, static_cast<uint_least8_t>(sendRecvBit ? 0x80 : 0x00)};
+  result = writeMemory(commandReg, command);
+  if (result) {
+    return result;
+  }
+
+  uint_least8_t status;
+  result = pollBusy(&status);
+  if (!result) {
+    sendRecvBit = ((status & Status_SBR) == Status_SBR);
+  }
+  return result;
+}
+
+error_code DS2465::writeMemory(uint_least8_t addr,
+                               span<const uint_least8_t> buf) 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 = master->start(address_);
+  if (result) {
+    master->stop();
+    return result;
+  }
+  result = master->writeByte(addr);
+  if (result) {
+    master->stop();
+    return result;
+  }
+  result = master->writeBlock(buf);
+  if (result) {
+    master->stop();
+    return result;
+  }
+  result = master->stop();
+  return result;
+}
+
+error_code DS2465::readMemory(uint_least8_t addr,
+                              span<uint_least8_t> buf) 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 = master->start(address_);
+  if (result) {
+    master->stop();
+    return result;
+  }
+  result = master->writeByte(addr);
+  if (result) {
+    master->stop();
+    return result;
+  }
+  result = readMemory(buf);
+  return result;
+}
+
+error_code DS2465::readMemory(span<uint_least8_t> buf) const {
+  error_code result = master->start(address_ | 1);
+  if (result) {
+    master->stop();
+    return result;
+  }
+  result = master->readBlock(I2CMaster::Nack, buf);
+  if (result) {
+    master->stop();
+    return result;
+  }
+  result = master->stop();
+  return result;
+}
+
+error_code DS2465::writeConfig(Config config) {
+  const uint_least8_t configReg = 0x67;
+  uint_least8_t configBuf =
+      ((config.readByte() ^ 0xF) << 4) | config.readByte();
+  error_code result = writeMemory(configReg, make_span(&configBuf, 1));
+  if (!result) {
+    result = readMemory(configReg, make_span(&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 = 0x68;
+    break;
+  case tMSP_STD:
+  case tMSP_OD:
+    addr = 0x69;
+    break;
+  case tW0L_STD:
+  case tW0L_OD:
+    addr = 0x6A;
+    break;
+  case tREC0:
+    addr = 0x6B;
+    break;
+  case RWPU:
+    addr = 0x6C;
+    break;
+  case tW1L_OD:
+    addr = 0x6D;
+    break;
+  }
+
+  uint_least8_t data;
+  error_code result = readMemory(addr, make_span(&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, make_span(&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(make_span(&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 = 0xB4;
+  error_code result = writeMemory(commandReg, make_span(&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 = 0xF0;
+  error_code result = writeMemory(commandReg, make_span(&buf, 1));
+
+  if (!result) {
+    result = readMemory(make_span(&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(AuthenticationData::const_span data) {
+  error_code result = writeMemory(scratchpad, data);
+  if (!result) {
+    result = computeNextMasterSecret(false, 0, FullPage);
+  }
+  return result;
+}
+
+error_code
+DS2465::computeNextMasterSecretWithSwap(AuthenticationData::const_span data,
+                                        int pageNum, PageRegion region) {
+  error_code result = writeMemory(scratchpad, data);
+  if (!result) {
+    result = computeNextMasterSecret(true, pageNum, region);
+  }
+  return result;
+}
+
+error_code DS2465::computeWriteMac(WriteMacData::const_span data) const {
+  error_code result = writeMemory(scratchpad, data);
+  if (!result) {
+    result = computeWriteMac(false, false, 0, 0);
+  }
+  return result;
+}
+
+error_code DS2465::computeWriteMac(WriteMacData::const_span data,
+                                   Page::span mac) const {
+  error_code result = computeWriteMac(data);
+  if (!result) {
+    result = readMemory(mac);
+  }
+  return result;
+}
+
+error_code
+DS2465::computeAndTransmitWriteMac(WriteMacData::const_span data) const {
+  error_code result = computeWriteMac(data);
+  if (!result) {
+    result = writeMacBlock();
+  }
+  return result;
+}
+
+error_code DS2465::computeWriteMacWithSwap(WriteMacData::const_span data,
+                                           int pageNum, int segmentNum) const {
+  error_code result = writeMemory(scratchpad, data);
+  if (!result) {
+    result = computeWriteMac(false, true, pageNum, segmentNum);
+  }
+  return result;
+}
+
+error_code DS2465::computeWriteMacWithSwap(WriteMacData::const_span data,
+                                           int pageNum, int segmentNum,
+                                           Page::span mac) const {
+  error_code result = computeWriteMacWithSwap(data, pageNum, segmentNum);
+  if (!result) {
+    result = readMemory(mac);
+  }
+  return result;
+}
+
+error_code
+DS2465::computeAndTransmitWriteMacWithSwap(WriteMacData::const_span data,
+                                           int pageNum, int segmentNum) const {
+  error_code result = computeWriteMacWithSwap(data, pageNum, segmentNum);
+  if (!result) {
+    result = writeMacBlock();
+  }
+  return result;
+}
+
+error_code DS2465::computeSlaveSecret(AuthenticationData::const_span data) {
+  error_code result = writeMemory(scratchpad, data);
+  if (!result) {
+    result = computeSlaveSecret(false, 0, FullPage);
+  }
+  return result;
+}
+
+error_code
+DS2465::computeSlaveSecretWithSwap(AuthenticationData::const_span data,
+                                   int pageNum, PageRegion region) {
+  error_code result = writeMemory(scratchpad, data);
+  if (!result) {
+    result = computeSlaveSecret(true, pageNum, region);
+  }
+  return result;
+}
+
+error_code DS2465::computeAuthMac(AuthenticationData::const_span data) const {
+  error_code result = writeMemory(scratchpad, data);
+  if (!result) {
+    result = computeAuthMac(false, 0, FullPage);
+  }
+  return result;
+}
+
+error_code DS2465::computeAuthMac(AuthenticationData::const_span data,
+                                  Page::span mac) const {
+  error_code result = computeAuthMac(data);
+  if (!result) {
+    result = readMemory(mac);
+  }
+  return result;
+}
+
+error_code
+DS2465::computeAndTransmitAuthMac(AuthenticationData::const_span data) const {
+  error_code result = computeAuthMac(data);
+  if (!result) {
+    result = writeMacBlock();
+  }
+  return result;
+}
+
+error_code DS2465::computeAuthMacWithSwap(AuthenticationData::const_span data,
+                                          int pageNum,
+                                          PageRegion region) const {
+  error_code result = writeMemory(scratchpad, data);
+  if (!result) {
+    result = computeAuthMac(true, pageNum, region);
+  }
+  return result;
+}
+
+error_code DS2465::computeAuthMacWithSwap(AuthenticationData::const_span data,
+                                          int pageNum, PageRegion region,
+                                          Page::span mac) const {
+  error_code result = computeAuthMacWithSwap(data, pageNum, region);
+  if (!result) {
+    result = readMemory(mac);
+  }
+  return result;
+}
+
+error_code DS2465::computeAndTransmitAuthMacWithSwap(
+    AuthenticationData::const_span 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 MaximInterfaceDevices
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS2465.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,420 @@
+/*******************************************************************************
+* 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 MaximInterfaceDevices_DS2465
+#define MaximInterfaceDevices_DS2465
+
+#include <MaximInterfaceCore/array_span.hpp>
+#include <MaximInterfaceCore/I2CMaster.hpp>
+#include <MaximInterfaceCore/OneWireMaster.hpp>
+#include <MaximInterfaceCore/Sleep.hpp>
+#include "Config.hpp"
+
+namespace MaximInterfaceDevices {
+
+/// Interface to the DS2465 1-Wire master and SHA-256 coprocessor.
+class DS2465 : public Core::OneWireMaster {
+public:
+  enum ErrorValue { HardwareError = 1, ArgumentOutOfRangeError };
+
+  /// @brief 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 Core::array_span<uint_least8_t, 4> Segment;
+
+  /// Holds the contents of a device memory page.
+  typedef Core::array_span<uint_least8_t, 32> Page;
+
+  /// Data for Compute Write MAC operation.
+  typedef Core::array_span<uint_least8_t, 20> WriteMacData;
+
+  /// Data for the Compute Auth. MAC and Compute Slave Secret operations.
+  typedef Core::array_span<uint_least8_t, 76> AuthenticationData;
+
+  static const int memoryPages = 2;
+  static const int segmentsPerPage = Page::size / Segment::size;
+
+  /// Represents a DS2465 configuration.
+  class Config {
+  public:
+    /// Default construct with power-on config.
+    explicit Config(uint_least8_t readByte = optionAPU)
+        : readByte_(readByte & 0xF) {}
+
+    /// @name 1WS
+    /// @brief 1-Wire Speed
+    /// @{
+
+    /// Get 1WS bit.
+    bool get1WS() const { return (readByte_ & option1WS) == option1WS; }
+
+    /// Set 1WS bit.
+    Config & set1WS(bool new1WS) {
+      if (new1WS) {
+        readByte_ |= option1WS;
+      } else {
+        readByte_ &= ~option1WS;
+      }
+      return *this;
+    }
+
+    /// @}
+
+    /// @name SPU
+    /// @brief Strong Pullup
+    /// @{
+
+    /// Get SPU bit.
+    bool getSPU() const { return (readByte_ & optionSPU) == optionSPU; }
+
+    /// Set SPU bit.
+    Config & setSPU(bool newSPU) {
+      if (newSPU) {
+        readByte_ |= optionSPU;
+      } else {
+        readByte_ &= ~optionSPU;
+      }
+      return *this;
+    }
+
+    /// @}
+
+    /// @name PDN
+    /// @brief 1-Wire Power Down
+    /// @{
+
+    /// Get PDN bit.
+    bool getPDN() const { return (readByte_ & optionPDN) == optionPDN; }
+
+    /// Set PDN bit.
+    Config & setPDN(bool newPDN) {
+      if (newPDN) {
+        readByte_ |= optionPDN;
+      } else {
+        readByte_ &= ~optionPDN;
+      }
+      return *this;
+    }
+
+    /// @}
+
+    /// @name APU
+    /// @brief Active Pullup
+    /// @{
+
+    /// Get APU bit.
+    bool getAPU() const { return (readByte_ & optionAPU) == optionAPU; }
+
+    /// Set APU bit.
+    Config & setAPU(bool newAPU) {
+      if (newAPU) {
+        readByte_ |= optionAPU;
+      } else {
+        readByte_ &= ~optionAPU;
+      }
+      return *this;
+    }
+
+    /// @}
+
+    /// 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(Core::Sleep & sleep, Core::I2CMaster & master,
+         uint_least8_t address = 0x30)
+      : sleep(&sleep), master(&master), address_(address & 0xFE) {}
+
+  void setSleep(Core::Sleep & sleep) { this->sleep = &sleep; }
+
+  void setMaster(Core::I2CMaster & master) { this->master = &master; }
+
+  uint_least8_t address() const { return address_; }
+
+  void setAddress(uint_least8_t address) { address_ = address & 0xFE; }
+
+  /// Initialize hardware for use.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  initialize(Config config = Config());
+
+  /// @brief Write a new configuration to the DS2465.
+  /// @param[in] config New configuration to write.
+  MaximInterfaceDevices_EXPORT Core::error_code writeConfig(Config config);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writePortParameter(PortParameter param, int val);
+
+  // 1-Wire Master Commands
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code reset();
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  touchBitSetLevel(bool & sendRecvBit, Level afterLevel);
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  readBlock(Core::span<uint_least8_t> recvBuf);
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  writeBlock(Core::span<const uint_least8_t> sendBuf);
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  setSpeed(Speed newSpeed);
+
+  /// @copydoc Core::OneWireMaster::setLevel
+  /// @note
+  /// The DS2465 only supports enabling strong pullup following a 1-Wire read or
+  /// write operation.
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  setLevel(Level newLevel);
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  triplet(TripletData & data);
+
+  // DS2465 Coprocessor Commands
+
+  /// @brief Read data from an EEPROM memory page.
+  /// @param pageNum Page number to read from.
+  /// @param[out] data Data that was read.
+  MaximInterfaceDevices_EXPORT Core::error_code readPage(int pageNum,
+                                                         Page::span data) const;
+
+  /// @brief Write data to an EEPROM memory page.
+  /// @param pageNum Page number to copy to.
+  /// @param data Data to write.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writePage(int pageNum, Page::const_span data);
+
+  /// @brief Write data to an EEPROM memory segment.
+  /// @param pageNum Page number to copy to.
+  /// @param segmentNum Segment number to copy to.
+  /// @param data Data to write.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeSegment(int pageNum, int segmentNum, Segment::const_span data);
+
+  /// Write data to the secret EEPROM memory page.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeMasterSecret(Page::const_span masterSecret);
+
+  /// @brief Compute Next Master Secret.
+  /// @param data Combined data fields for computation.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeNextMasterSecret(AuthenticationData::const_span data);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeNextMasterSecretWithSwap(AuthenticationData::const_span data,
+                                  int pageNum, PageRegion region);
+
+  /// @brief Compute Write MAC.
+  /// @param data Combined data fields for computation.
+  /// @param[out] mac Computed Write MAC.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeWriteMac(WriteMacData::const_span data, Page::span mac) const;
+
+  /// @brief Compute Write MAC.
+  /// @param data Combined data fields for computation.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeAndTransmitWriteMac(WriteMacData::const_span data) const;
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeWriteMacWithSwap(WriteMacData::const_span data, int pageNum,
+                          int segmentNum, Page::span mac) const;
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeAndTransmitWriteMacWithSwap(WriteMacData::const_span data, int pageNum,
+                                     int segmentNum) const;
+
+  /// @brief Compute Slave Secret (S-Secret).
+  /// @param data Combined data fields for computation.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeSlaveSecret(AuthenticationData::const_span data);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeSlaveSecretWithSwap(AuthenticationData::const_span data, int pageNum,
+                             PageRegion region);
+
+  /// @brief Compute Authentication MAC.
+  /// @param data Combined data fields for computation.
+  /// @param[out] mac Computed Auth MAC.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeAuthMac(AuthenticationData::const_span data, Page::span mac) const;
+
+  /// @brief Compute Authentication MAC.
+  /// @param data Combined data fields for computation.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeAndTransmitAuthMac(AuthenticationData::const_span data) const;
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeAuthMacWithSwap(AuthenticationData::const_span data, int pageNum,
+                         PageRegion region, Page::span mac) const;
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeAndTransmitAuthMacWithSwap(AuthenticationData::const_span data,
+                                    int pageNum, PageRegion region) const;
+
+  MaximInterfaceDevices_EXPORT static const Core::error_category &
+  errorCategory();
+
+private:
+  const Core::Sleep * sleep;
+  Core::I2CMaster * master;
+  uint_least8_t address_;
+  Config curConfig;
+
+  /// @brief Performs a soft reset on the DS2465.
+  /// @note This is not a 1-Wire Reset.
+  Core::error_code resetDevice();
+
+  /// @brief
+  /// 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.
+  Core::error_code pollBusy(uint_least8_t * pStatus = NULL) const;
+
+  /// @brief Ensure that the desired 1-Wire level is set in the configuration.
+  /// @param level Desired 1-Wire level.
+  Core::error_code configureLevel(Level level);
+
+  /// @note Const since only for internal use.
+  Core::error_code writeMemory(uint_least8_t addr,
+                               Core::span<const uint_least8_t> buf) const;
+
+  /// @brief Read memory from the DS2465.
+  /// @param addr Address to begin reading from.
+  /// @param[out] buf Buffer to hold read data.
+  Core::error_code readMemory(uint_least8_t addr,
+                              Core::span<uint_least8_t> buf) const;
+
+  /// @brief Read memory from the DS2465 at the current pointer.
+  /// @param[out] buf Buffer to hold read data.
+  Core::error_code readMemory(Core::span<uint_least8_t> buf) const;
+
+  /// Write the last computed MAC to the 1-Wire bus.
+  Core::error_code writeMacBlock() const;
+
+  Core::error_code computeWriteMac(WriteMacData::const_span data) const;
+
+  Core::error_code computeWriteMacWithSwap(WriteMacData::const_span data,
+                                           int pageNum, int segmentNum) const;
+
+  Core::error_code computeAuthMac(AuthenticationData::const_span data) const;
+
+  Core::error_code computeAuthMacWithSwap(AuthenticationData::const_span data,
+                                          int pageNum, PageRegion region) const;
+
+  // Legacy implementations
+  Core::error_code copyScratchpad(bool destSecret, int pageNum, bool notFull,
+                                  int segmentNum);
+
+  Core::error_code computeNextMasterSecret(bool swap, int pageNum,
+                                           PageRegion region);
+
+  Core::error_code computeWriteMac(bool regwrite, bool swap, int pageNum,
+                                   int segmentNum) const;
+
+  Core::error_code computeSlaveSecret(bool swap, int pageNum,
+                                      PageRegion region);
+
+  Core::error_code computeAuthMac(bool swap, int pageNum,
+                                  PageRegion region) const;
+};
+
+inline Core::error_code make_error_code(DS2465::ErrorValue e) {
+  return Core::error_code(e, DS2465::errorCategory());
+}
+
+} // namespace MaximInterfaceDevices
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS2480B.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,561 @@
+/*******************************************************************************
+* 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 <MaximInterfaceCore/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
+
+// Baud rate bits
+#define PARMSET_9600 0x00
+#define PARMSET_19200 0x02
+#define PARMSET_57600 0x04
+#define PARMSET_115200 0x06
+
+// DS2480B program voltage available
+#define DS2480BPROG_MASK 0x20
+
+namespace MaximInterfaceDevices {
+
+using namespace Core;
+
+error_code DS2480B::initialize() {
+  level = NormalLevel;
+  mode = MODSEL_COMMAND;
+  speed = SPEEDSEL_STD;
+
+  // Send a break to reset the DS2480B.
+  // Switch to lower baud rate to ensure break is longer than 2 ms.
+  error_code result = uart->setBaudRate(4800);
+  if (result) {
+    return result;
+  }
+  result = uart->sendBreak();
+  if (result) {
+    return result;
+  }
+  result = uart->setBaudRate(9600);
+  if (result) {
+    return result;
+  }
+
+  // Wait for master reset.
+  sleep->invoke(1);
+
+  // Flush the read buffer.
+  result = uart->clearReadBuffer();
+  if (result) {
+    return result;
+  }
+
+  // Send the timing byte.
+  result = uart->writeByte(CMD_COMM | FUNCTSEL_RESET | SPEEDSEL_STD);
+  if (result) {
+    return result;
+  }
+
+  // Change the DS2480 baud rate.
+  result = uart->writeByte(CMD_CONFIG | PARMSEL_BAUDRATE | PARMSET_115200);
+  if (result) {
+    return result;
+  }
+
+  // Change our baud rate.
+  result = uart->setBaudRate(115200);
+  if (result) {
+    return result;
+  }
+
+  uint_least8_t response;
+
+  // Verify response.
+  result = uart->readByte(response);
+  if (result) {
+    return result;
+  }
+  if ((response & (PARMSEL_MASK | PARMSET_MASK)) !=
+      (PARMSEL_BAUDRATE | PARMSET_115200)) {
+    return make_error_code(HardwareError);
+  }
+
+  // Set the SPUD time value.
+  result = uart->writeByte(CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite);
+  if (result) {
+    return result;
+  }
+
+  // Verify response.
+  result = uart->readByte(response);
+  if (result) {
+    return result;
+  }
+  if ((response & (PARMSEL_MASK | PARMSET_MASK)) !=
+      (PARMSEL_5VPULSE | PARMSET_infinite)) {
+    return make_error_code(HardwareError);
+  }
+
+  return result;
+}
+
+error_code DS2480B::reset() {
+  if (level != NormalLevel) {
+    return make_error_code(InvalidLevelError);
+  }
+
+  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;
+
+  // Send the packet.
+  error_code result = uart->writeBlock(make_span(packet, packetLen));
+  if (result) {
+    return result;
+  }
+
+  // Read back the response.
+  result = uart->readByte(packet[0]);
+  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) {
+  if (level != NormalLevel) {
+    return make_error_code(InvalidLevelError);
+  }
+
+  uint_least8_t packet[3];
+  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_BIT |
+                        (sendRecvBit ? BITPOL_ONE : BITPOL_ZERO) | speed;
+  switch (afterLevel) {
+  case NormalLevel:
+    break;
+
+  case StrongLevel:
+    // Add the command to begin the pulse.
+    packet[packetLen++] =
+        CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE;
+    break;
+
+  default:
+    return make_error_code(InvalidLevelError);
+  }
+
+  // Send the packet.
+  error_code result = uart->writeBlock(make_span(packet, packetLen));
+  if (result) {
+    return result;
+  }
+
+  // Read back the response.
+  result = uart->readByte(packet[0]);
+  if (result) {
+    return result;
+  }
+
+  // Interpret the response.
+  if ((packet[0] & 0xE0) == 0x80) {
+    sendRecvBit = ((packet[0] & RB_BIT_MASK) == RB_BIT_ONE);
+    level = afterLevel;
+  } else {
+    result = make_error_code(HardwareError);
+  }
+  return result;
+}
+
+error_code DS2480B::writeByteSetLevel(uint_least8_t sendByte,
+                                      Level afterLevel) {
+  if (level != NormalLevel) {
+    return make_error_code(InvalidLevelError);
+  }
+
+  switch (afterLevel) {
+  case NormalLevel:
+    break;
+
+  case StrongLevel:
+    return OneWireMaster::writeByteSetLevel(sendByte, afterLevel);
+
+  default:
+    return make_error_code(InvalidLevelError);
+  }
+
+  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;
+  }
+
+  // Send the packet.
+  error_code result = uart->writeBlock(make_span(packet, packetLen));
+  if (result) {
+    return result;
+  }
+
+  // Read back the response.
+  result = uart->readByte(packet[0]);
+  if (result) {
+    return result;
+  }
+
+  // Interpret the response.
+  if (packet[0] != sendByte) {
+    result = make_error_code(HardwareError);
+  }
+  return result;
+}
+
+error_code DS2480B::readByteSetLevel(uint_least8_t & recvByte,
+                                     Level afterLevel) {
+  if (level != NormalLevel) {
+    return make_error_code(InvalidLevelError);
+  }
+
+  switch (afterLevel) {
+  case NormalLevel:
+    break;
+
+  case StrongLevel:
+    return OneWireMaster::readByteSetLevel(recvByte, afterLevel);
+
+  default:
+    return make_error_code(InvalidLevelError);
+  }
+
+  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;
+
+  // Send the packet.
+  error_code result = uart->writeBlock(make_span(packet, packetLen));
+  if (result) {
+    return result;
+  }
+
+  // Read back the response.
+  result = uart->readByte(recvByte);
+  return result;
+}
+
+error_code DS2480B::setSpeed(Speed newSpeed) {
+  uint_least8_t newSpeedByte;
+  switch (newSpeed) {
+  case OverdriveSpeed:
+    newSpeedByte = SPEEDSEL_OD;
+    break;
+
+  case StandardSpeed:
+    newSpeedByte = SPEEDSEL_STD;
+    break;
+
+  default:
+    return make_error_code(InvalidSpeedError);
+  }
+  if (speed == newSpeedByte) {
+    return error_code();
+  }
+  speed = newSpeedByte;
+
+  uint_least8_t packet[2];
+  int packetLen = 0;
+
+  // Check for correct mode.
+  if (mode != MODSEL_COMMAND) {
+    mode = MODSEL_COMMAND;
+    packet[packetLen++] = MODE_COMMAND;
+  }
+
+  // Change DS2480 speed.
+  packet[packetLen++] = CMD_COMM | FUNCTSEL_SEARCHOFF | speed;
+
+  // Send the packet.
+  return uart->writeBlock(make_span(packet, packetLen));
+}
+
+error_code DS2480B::setLevel(Level newLevel) {
+  if (level == newLevel) {
+    return error_code();
+  }
+
+  uint_least8_t packet[2];
+  int packetLen = 0;
+
+  switch (newLevel) {
+  case NormalLevel:
+    // Stop pulse command.
+    packet[packetLen++] = MODE_STOP_PULSE;
+    break;
+
+  case StrongLevel:
+    // Check for correct mode.
+    if (mode != MODSEL_COMMAND) {
+      mode = MODSEL_COMMAND;
+      packet[packetLen++] = MODE_COMMAND;
+    }
+
+    // Add the command to begin the pulse.
+    packet[packetLen++] =
+        CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE;
+    break;
+
+  default:
+    return make_error_code(InvalidLevelError);
+  }
+
+  // Send the packet.
+  error_code result = uart->writeBlock(make_span(packet, packetLen));
+  if (result) {
+    return result;
+  }
+
+  if (newLevel == NormalLevel) {
+    // Read back the response.
+    result = uart->readByte(packet[0]);
+    if (result) {
+      return result;
+    }
+
+    // Interpret the response.
+    if ((packet[0] & 0xE0) != 0xE0) {
+      return make_error_code(HardwareError);
+    }
+  }
+
+  level = newLevel;
+  return result;
+}
+
+error_code DS2480B::sendCommand(uint_least8_t command) {
+  uint_least8_t packet[2];
+  int packetLen = 0;
+
+  // Check for correct mode.
+  if (mode != MODSEL_COMMAND) {
+    mode = MODSEL_COMMAND;
+    packet[packetLen++] = MODE_COMMAND;
+  }
+
+  // Add command.
+  packet[packetLen++] = command;
+
+  // Send the packet.
+  return uart->writeBlock(make_span(packet, packetLen));
+}
+
+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 MaximInterfaceDevices
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS2480B.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,96 @@
+/*******************************************************************************
+* 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 MaximInterfaceDevices_DS2480B
+#define MaximInterfaceDevices_DS2480B
+
+#include <MaximInterfaceCore/OneWireMaster.hpp>
+#include <MaximInterfaceCore/Sleep.hpp>
+#include <MaximInterfaceCore/Uart.hpp>
+#include "Config.hpp"
+
+namespace MaximInterfaceDevices {
+
+/// Serial to 1-Wire Line Driver
+class DS2480B : public Core::OneWireMaster {
+public:
+  enum ErrorValue { HardwareError = 1 };
+
+  DS2480B(Core::Sleep & sleep, Core::Uart & uart)
+      : sleep(&sleep), uart(&uart) {}
+
+  void setSleep(Core::Sleep & sleep) { this->sleep = &sleep; }
+
+  void setUart(Core::Uart & uart) { this->uart = &uart; }
+
+  MaximInterfaceDevices_EXPORT Core::error_code initialize();
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code reset();
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  touchBitSetLevel(bool & sendRecvBit, Level afterLevel);
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  setSpeed(Speed newSpeed);
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  setLevel(Level newLevel);
+
+  MaximInterfaceDevices_EXPORT static const Core::error_category &
+  errorCategory();
+
+protected:
+  MaximInterfaceDevices_EXPORT Core::error_code
+  sendCommand(uint_least8_t command);
+
+private:
+  const Core::Sleep * sleep;
+  Core::Uart * uart;
+
+  Level level;
+  uint_least8_t mode;
+  uint_least8_t speed;
+};
+
+inline Core::error_code make_error_code(DS2480B::ErrorValue e) {
+  return Core::error_code(e, DS2480B::errorCategory());
+}
+
+} // namespace MaximInterfaceDevices
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS2482_DS2484.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,426 @@
+/*******************************************************************************
+* 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 <MaximInterfaceCore/Error.hpp>
+#include "DS2482_DS2484.hpp"
+
+namespace MaximInterfaceDevices {
+
+using namespace Core;
+
+// 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) {
+  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
+
+  error_code result = sendCommand(0xF0);
+  if (result) {
+    return result;
+  }
+
+  uint_least8_t buf;
+  result = readRegister(buf);
+  if (result) {
+    return result;
+  }
+
+  if ((buf & 0xF7) != 0x10) {
+    return make_error_code(HardwareError);
+  }
+
+  // Do a command to get 1-Wire master reset out of holding state.
+  reset();
+
+  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(0x78, data.writeBit ? 0x80 : 0x00);
+  if (!result) {
+    uint_least8_t status;
+    result = pollBusy(&status);
+    if (!result) {
+      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(0xB4);
+  if (result) {
+    return result;
+  }
+
+  uint_least8_t buf;
+  result = pollBusy(&buf);
+  if (result) {
+    return 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) {
+    return result;
+  }
+
+  result = sendCommand(0x87, sendRecvBit ? 0x80 : 0x00);
+  if (result) {
+    return result;
+  }
+
+  uint_least8_t status;
+  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(0xA5, sendByte);
+  if (result) {
+    return 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(0x96);
+  if (result) {
+    return result;
+  }
+
+  result = pollBusy();
+  if (result) {
+    return result;
+  }
+
+  result = readRegister(0xE1, recvByte);
+  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
+  return writeConfig(Config(curConfig).set1WS(newSpeed == OverdriveSpeed));
+}
+
+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(0xD2, configBuf);
+  if (!result) {
+    result = readRegister(0xC3, 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(0xE1, reg);
+  if (!result) {
+    result = readRegister(buf);
+  }
+  return result;
+}
+
+error_code DS2482_DS2484::readRegister(uint_least8_t & buf) const {
+  return master->readPacket(address_, make_span(&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
+  return writeConfig(Config(curConfig).setSPU(level == StrongLevel));
+}
+
+error_code DS2482_DS2484::sendCommand(uint_least8_t cmd) const {
+  return master->writePacket(address_, make_span(&cmd, 1));
+}
+
+error_code DS2482_DS2484::sendCommand(uint_least8_t cmd,
+                                      uint_least8_t param) const {
+  uint_least8_t buf[] = {cmd, param};
+  return master->writePacket(address_, buf);
+}
+
+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(0xC3, 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(0xC3, (param << 4) | val);
+  if (result) {
+    return result;
+  }
+
+  uint_least8_t portConfig = val + 1;
+  for (int reads = -1; reads < param; ++reads) {
+    result = readRegister(portConfig);
+    if (result) {
+      return result;
+    }
+  }
+  if (val != portConfig) {
+    result = make_error_code(HardwareError);
+  }
+
+  return result;
+}
+
+} // namespace MaximInterfaceDevices
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS2482_DS2484.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,267 @@
+/*******************************************************************************
+* 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 MaximInterfaceDevices_DS2482_DS2484
+#define MaximInterfaceDevices_DS2482_DS2484
+
+#include <MaximInterfaceCore/I2CMaster.hpp>
+#include <MaximInterfaceCore/OneWireMaster.hpp>
+#include "Config.hpp"
+
+namespace MaximInterfaceDevices {
+
+/// Interface to the DS2484, DS2482-100, DS2482-101, DS2482-800 1-Wire masters.
+class DS2482_DS2484 : public Core::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) {}
+
+    /// @name 1WS
+    /// @brief 1-Wire Speed
+    /// @{
+
+    /// Get 1WS bit.
+    bool get1WS() const { return (readByte_ & option1WS) == option1WS; }
+
+    /// Set 1WS bit.
+    Config & set1WS(bool new1WS) {
+      if (new1WS) {
+        readByte_ |= option1WS;
+      } else {
+        readByte_ &= ~option1WS;
+      }
+      return *this;
+    }
+
+    /// @}
+
+    /// @name SPU
+    /// @brief Strong Pullup
+    /// @{
+
+    /// Get SPU bit.
+    bool getSPU() const { return (readByte_ & optionSPU) == optionSPU; }
+
+    /// Set SPU bit.
+    Config & setSPU(bool newSPU) {
+      if (newSPU) {
+        readByte_ |= optionSPU;
+      } else {
+        readByte_ &= ~optionSPU;
+      }
+      return *this;
+    }
+
+    /// @}
+
+    /// @name PDN
+    /// @brief 1-Wire Power Down
+    /// @{
+
+    /// Get PDN bit.
+    bool getPDN() const { return (readByte_ & optionPDN) == optionPDN; }
+
+    /// Set PDN bit.
+    Config & setPDN(bool newPDN) {
+      if (newPDN) {
+        readByte_ |= optionPDN;
+      } else {
+        readByte_ &= ~optionPDN;
+      }
+      return *this;
+    }
+
+    /// @}
+
+    /// @name APU
+    /// @brief Active Pullup
+    /// @{
+
+    /// Get APU bit.
+    bool getAPU() const { return (readByte_ & optionAPU) == optionAPU; }
+
+    /// Set APU bit.
+    Config & setAPU(bool newAPU) {
+      if (newAPU) {
+        readByte_ |= optionAPU;
+      } else {
+        readByte_ &= ~optionAPU;
+      }
+      return *this;
+    }
+
+    /// @}
+
+    /// 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 setMaster(Core::I2CMaster & master) { this->master = &master; }
+
+  uint_least8_t address() const { return address_; }
+
+  void setAddress(uint_least8_t address) { address_ = address; }
+
+  /// Initialize hardware for use.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  initialize(Config config = Config());
+
+  /// @brief Write a new configuration to the device.
+  /// @param[in] config New configuration to write.
+  MaximInterfaceDevices_EXPORT Core::error_code writeConfig(Config config);
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  triplet(TripletData & data);
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code reset();
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  touchBitSetLevel(bool & sendRecvBit, Level afterLevel);
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  setSpeed(Speed newSpeed);
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  setLevel(Level newLevel);
+
+  MaximInterfaceDevices_EXPORT static const Core::error_category &
+  errorCategory();
+
+protected:
+  DS2482_DS2484(Core::I2CMaster & master, uint_least8_t address)
+      : master(&master), address_(address) {}
+
+  /// @note Allow marking const since not public.
+  Core::error_code sendCommand(uint_least8_t cmd) const;
+
+  /// @note Allow marking const since not public.
+  Core::error_code sendCommand(uint_least8_t cmd, uint_least8_t param) const;
+
+  /// @brief Reads a register from the device.
+  /// @param reg Register to read from.
+  /// @param[out] buf Buffer to hold read data.
+  Core::error_code readRegister(uint_least8_t reg, uint_least8_t & buf) const;
+
+  /// @brief Reads the current register from the device.
+  /// @param[out] buf Buffer to hold read data.
+  Core::error_code readRegister(uint_least8_t & buf) const;
+
+private:
+  /// @brief Performs a soft reset on the device.
+  /// @note This is not a 1-Wire Reset.
+  Core::error_code resetDevice();
+
+  /// @brief
+  /// 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.
+  Core::error_code pollBusy(uint_least8_t * pStatus = NULL);
+
+  /// @brief Ensure that the desired 1-Wire level is set in the configuration.
+  /// @param level Desired 1-Wire level.
+  Core::error_code configureLevel(Level level);
+
+  Core::I2CMaster * master;
+  uint_least8_t address_;
+  Config curConfig;
+};
+
+inline Core::error_code make_error_code(DS2482_DS2484::ErrorValue e) {
+  return Core::error_code(e, DS2482_DS2484::errorCategory());
+}
+
+class DS2482_100 : public DS2482_DS2484 {
+public:
+  DS2482_100(Core::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(Core::I2CMaster & i2c_bus, uint_least8_t adrs)
+      : DS2482_DS2484(i2c_bus, adrs) {}
+
+  /// @brief Select the active 1-Wire channel.
+  /// @param channel Channel number to select from 0 to 7.
+  MaximInterfaceDevices_EXPORT Core::error_code selectChannel(int channel);
+};
+
+/// DS2484 I2C to 1-Wire Master
+class DS2484 : public DS2482_DS2484 {
+public:
+  /// @brief 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(Core::I2CMaster & i2c_bus, uint_least8_t adrs = 0x30)
+      : DS2482_DS2484(i2c_bus, adrs) {}
+
+  /// @brief Adjust 1-Wire port parameters.
+  /// @param param Parameter to adjust.
+  /// @param val New parameter value to set. Consult datasheet for value mappings.
+  MaximInterfaceDevices_EXPORT Core::error_code adjustPort(PortParameter param,
+                                                           int val);
+};
+
+} // namespace MaximInterfaceDevices
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS28C36_DS2476.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,725 @@
+/*******************************************************************************
+* 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 <MaximInterfaceCore/Error.hpp>
+#include <MaximInterfaceCore/I2CMaster.hpp>
+#include <MaximInterfaceCore/RomId.hpp>
+#include "DS28C36_DS2476.hpp"
+
+namespace MaximInterfaceDevices {
+
+using namespace Core;
+using namespace Ecc256;
+using std::copy;
+
+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;
+}
+
+const int DS28C36::publicKeyAxPage;
+const int DS28C36::publicKeyAyPage;
+const int DS28C36::publicKeyBxPage;
+const int DS28C36::publicKeyByPage;
+const int DS28C36::publicKeyCxPage;
+const int DS28C36::publicKeyCyPage;
+const int DS28C36::privateKeyAPage;
+const int DS28C36::privateKeyBPage;
+const int DS28C36::privateKeyCPage;
+const int DS28C36::secretAPage;
+const int DS28C36::secretBPage;
+const int DS28C36::decrementCounterPage;
+const int DS28C36::romOptionsPage;
+const int DS28C36::gpioControlPage;
+const int DS28C36::publicKeySxPage;
+const int DS28C36::publicKeySyPage;
+const int DS28C36::memoryPages;
+
+error_code DS28C36::writeMemory(int pageNum, Page::const_span page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[1 + Page::size];
+  buffer[0] = pageNum;
+  copy(page.begin(), page.end(), buffer + 1);
+  error_code result = writeCommand(0x96, buffer);
+  if (!result) {
+    sleep(writeMemoryTimeMs);
+    result = readFixedLengthResponse(make_span(buffer, 1));
+    if (!result) {
+      result = convertResultByte(buffer[0]);
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::readMemory(int pageNum, Page::span page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const uint_least8_t parameter = pageNum;
+  error_code result = writeCommand(0x69, make_span(&parameter, 1));
+  if (!result) {
+    sleep(readMemoryTimeMs);
+    array<uint_least8_t, 1 + Page::size> response;
+    result = readFixedLengthResponse(response);
+    if (!result) {
+      result = convertResultByte(response[0]);
+      copy(response.begin() + 1, response.end(), page.begin());
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::writeBuffer(span<const uint_least8_t> data) {
+  return writeCommand(0x87, data);
+}
+
+error_code DS28C36::readBuffer(std::vector<uint_least8_t> & data) {
+  error_code result = writeCommand(0x5A);
+  if (!result) {
+    data.resize(80);
+    span<uint_least8_t> dataSpan(data);
+    result = readVariableLengthResponse(dataSpan);
+    if (result) {
+      data.clear();
+    } else {
+      data.resize(dataSpan.size());
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::readPageProtection(int pageNum,
+                                       PageProtection & protection) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer = pageNum;
+  error_code result = writeCommand(0xAA, make_span(&buffer, 1));
+  if (!result) {
+    sleep(readMemoryTimeMs);
+    result = readFixedLengthResponse(make_span(&buffer, 1));
+    if (!result) {
+      protection = buffer;
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::setPageProtection(int pageNum,
+                                      const PageProtection & protection) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[] = {static_cast<uint_least8_t>(pageNum),
+                            static_cast<uint_least8_t>(protection.to_ulong())};
+  error_code result = writeCommand(0xC3, buffer);
+  if (!result) {
+    sleep(writeMemoryTimeMs);
+    result = readFixedLengthResponse(make_span(buffer, 1));
+    if (!result) {
+      result = convertResultByte(buffer[0]);
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::decrementCounter() {
+  error_code result = writeCommand(0xC9);
+  if (!result) {
+    sleep(writeMemoryTimeMs);
+    uint_least8_t response;
+    result = readFixedLengthResponse(make_span(&response, 1));
+    if (!result) {
+      result = convertResultByte(response);
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::readRng(span<uint_least8_t> data) {
+  if ((data.size() < 1) || (data.size() > 64)) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  data[0] = static_cast<uint_least8_t>(data.size() - 1);
+  error_code result = writeCommand(0xD2, data.first(1));
+  if (!result) {
+    sleep(sha256ComputationTimeMs);
+    result = readFixedLengthResponse(data);
+  }
+  return result;
+}
+
+error_code DS28C36::encryptedReadMemory(int pageNum, SecretNum secretNum,
+                                        EncryptionChallenge::span challenge,
+                                        Page::span data) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const uint_least8_t parameter = (secretNum << 6) | pageNum;
+  error_code result = writeCommand(0x4B, make_span(&parameter, 1));
+  if (!result) {
+    sleep(readMemoryTimeMs + sha256ComputationTimeMs);
+    uint_least8_t response[1 + EncryptionChallenge::size + Page::size];
+    result = readFixedLengthResponse(response);
+    if (!result) {
+      result = convertResultByte(response[0]);
+      const uint_least8_t * begin = response + 1;
+      const uint_least8_t * end = begin + challenge.size();
+      copy(begin, end, challenge.begin());
+      begin = end;
+      end = begin + data.size();
+      copy(begin, end, data.begin());
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::computeAndReadPageAuthentication(int pageNum,
+                                                     AuthType authType) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const uint_least8_t parameter = (authType << 5) | pageNum;
+  return writeCommand(0xA5, make_span(&parameter, 1));
+}
+
+error_code
+DS28C36::computeAndReadPageAuthentication(int pageNum, KeyNum keyNum,
+                                          Signature::span 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);
+  }
+  error_code result = computeAndReadPageAuthentication(pageNum, authType);
+  if (!result) {
+    sleep(readMemoryTimeMs + generateEcdsaSignatureTimeMs);
+    uint_least8_t response[1 + 2 * Scalar::size];
+    result = readFixedLengthResponse(response);
+    if (!result) {
+      result = convertResultByte(response[0]);
+      const uint_least8_t * begin = response + 1;
+      const uint_least8_t * 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::computeAndReadPageAuthentication(int pageNum,
+                                                     SecretNum secretNum,
+                                                     Page::span 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);
+  }
+  error_code result = computeAndReadPageAuthentication(pageNum, authType);
+  if (!result) {
+    sleep(readMemoryTimeMs + sha256ComputationTimeMs);
+    array<uint_least8_t, 1 + Page::size> response;
+    result = readFixedLengthResponse(response);
+    if (!result) {
+      result = convertResultByte(response[0]);
+      copy(response.begin() + 1, response.end(), hmac.begin());
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::authenticatedSha2WriteMemory(int pageNum,
+                                                 SecretNum secretNum,
+                                                 Page::const_span page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[1 + Page::size];
+  buffer[0] = (secretNum << 6) | pageNum;
+  copy(page.begin(), page.end(), buffer + 1);
+  error_code result = writeCommand(0x99, buffer);
+  if (!result) {
+    sleep(writeMemoryTimeMs + (2 * sha256ComputationTimeMs));
+    result = readFixedLengthResponse(make_span(buffer, 1));
+    if (!result) {
+      result = convertResultByte(buffer[0]);
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::computeAndLockSha2Secret(int pageNum, SecretNum msecretNum,
+                                             SecretNum dsecretNum,
+                                             bool writeProtectEnable) {
+  // User pages only
+  if (pageNum < 0 || pageNum > 15) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[] = {
+      static_cast<uint_least8_t>((dsecretNum << 6) | (msecretNum << 4) |
+                                 pageNum),
+      static_cast<uint_least8_t>(writeProtectEnable ? 0x80 : 0x00)};
+  error_code result = writeCommand(0x3C, buffer);
+  if (!result) {
+    sleep(sha256ComputationTimeMs +
+          ((writeProtectEnable ? 2 : 1) * writeMemoryTimeMs));
+    result = readFixedLengthResponse(make_span(buffer, 1));
+    if (!result) {
+      result = convertResultByte(buffer[0]);
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::generateEcc256KeyPair(KeyNum keyNum,
+                                          bool writeProtectEnable) {
+  if (keyNum == KeyNumS) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer = keyNum;
+  if (writeProtectEnable) {
+    buffer |= 0x80;
+  }
+  error_code result = writeCommand(0xCB, make_span(&buffer, 1));
+  if (!result) {
+    sleep(generateEccKeyPairTimeMs);
+    result = readFixedLengthResponse(make_span(&buffer, 1));
+    if (!result) {
+      result = convertResultByte(buffer);
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::computeMultiblockHash(bool firstBlock, bool lastBlock,
+                                          span<const uint_least8_t> data) {
+  const span<const uint_least8_t>::index_type maxDataSize = 64;
+
+  if (data.size() < 1 || data.size() > maxDataSize) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[1 + maxDataSize];
+  buffer[0] = 0;
+  if (firstBlock) {
+    buffer[0] |= 0x40;
+  }
+  if (lastBlock) {
+    buffer[0] |= 0x80;
+  }
+  copy(data.begin(), data.end(), buffer + 1);
+  error_code result = writeCommand(0x33, make_span(buffer, data.size() + 1));
+  if (!result) {
+    sleep(sha256ComputationTimeMs);
+    result = readFixedLengthResponse(make_span(buffer, 1));
+    if (!result) {
+      result = convertResultByte(buffer[0]);
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::verifyEcdsaSignature(KeyNum keyNum, HashType hashType,
+                                         Signature::const_span signature,
+                                         PioState pioa, PioState piob) {
+  uint_least8_t buffer[1 + 2 * Scalar::size];
+  buffer[0] = keyNum | (hashType << 2);
+  if (pioa != Unchanged) {
+    buffer[0] |= 0x20;
+  }
+  if (pioa == Conducting) {
+    buffer[0] |= 0x10;
+  }
+  if (piob != Unchanged) {
+    buffer[0] |= 0x80;
+  }
+  if (piob == Conducting) {
+    buffer[0] |= 0x40;
+  }
+  uint_least8_t * bufferIt =
+      copy(signature.r.begin(), signature.r.end(), buffer + 1);
+  copy(signature.s.begin(), signature.s.end(), bufferIt);
+  error_code result = writeCommand(0x59, buffer);
+  if (!result) {
+    sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs +
+          ((hashType == DataInBuffer) ? sha256ComputationTimeMs : 0));
+    result = readFixedLengthResponse(make_span(buffer, 1));
+    if (!result) {
+      result = convertResultByte(buffer[0]);
+    }
+  }
+  return result;
+}
+
+error_code
+DS28C36::authenticateEcdsaPublicKey(bool authWrites, bool ecdh, KeyNum keyNum,
+                                    int csOffset,
+                                    Signature::const_span signature) {
+  if (((keyNum != KeyNumA) && (keyNum != KeyNumB)) || (csOffset < 0) ||
+      (csOffset > 31)) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[1 + 2 * Scalar::size];
+  buffer[0] = (csOffset << 3) | (keyNum << 2);
+  if (ecdh) {
+    buffer[0] |= 0x02;
+  }
+  if (authWrites) {
+    buffer[0] |= 0x01;
+  }
+  uint_least8_t * bufferIt =
+      copy(signature.r.begin(), signature.r.end(), buffer + 1);
+  copy(signature.s.begin(), signature.s.end(), bufferIt);
+  error_code result = writeCommand(0xA8, buffer);
+  if (!result) {
+    sleep((ecdh ? 2 : 1) * verifyEsdsaSignatureOrComputeEcdhTimeMs);
+    result = readFixedLengthResponse(make_span(buffer, 1));
+    if (!result) {
+      result = convertResultByte(buffer[0]);
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::authenticatedEcdsaWriteMemory(int pageNum,
+                                                  Page::const_span page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[1 + Page::size];
+  buffer[0] = pageNum;
+  copy(page.begin(), page.end(), buffer + 1);
+  error_code result = writeCommand(0x89, buffer);
+  if (!result) {
+    sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs + writeMemoryTimeMs +
+          sha256ComputationTimeMs);
+    result = readFixedLengthResponse(make_span(buffer, 1));
+    if (!result) {
+      result = convertResultByte(buffer[0]);
+    }
+  }
+  return result;
+}
+
+error_code DS28C36::writeCommand(uint_least8_t command,
+                                 span<const uint_least8_t> parameters) {
+  error_code result = master->start(address_);
+  if (result) {
+    master->stop();
+    return result;
+  }
+  result = master->writeByte(command);
+  if (result) {
+    master->stop();
+    return result;
+  }
+  if (!parameters.empty()) {
+    result = master->writeByte(static_cast<uint_least8_t>(parameters.size()));
+    if (result) {
+      master->stop();
+      return result;
+    }
+    result = master->writeBlock(parameters);
+    if (result) {
+      master->stop();
+      return result;
+    }
+  }
+  result = master->stop();
+  return result;
+}
+
+error_code DS28C36::readVariableLengthResponse(span<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;
+  }
+  if (length > response.size()) {
+    master->stop();
+    return make_error_code(InvalidResponseError);
+  }
+  response = response.first(length);
+  if (!response.empty()) {
+    result = master->readBlock(I2CMaster::Nack, response);
+    if (result) {
+      master->stop();
+      return result;
+    }
+  }
+  result = master->stop();
+  return result;
+}
+
+error_code DS28C36::readFixedLengthResponse(span<uint_least8_t> response) {
+  const span<uint_least8_t>::index_type requestedResponseSize = response.size();
+  error_code result = readVariableLengthResponse(response);
+  if (!result && response.size() != requestedResponseSize) {
+    result = make_error_code(InvalidResponseError);
+  }
+  return result;
+}
+
+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 DS2476::generateEcdsaSignature(KeyNum keyNum,
+                                          Signature::span signature) {
+  if (keyNum == KeyNumS) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const uint_least8_t parameter = keyNum;
+  error_code result = writeCommand(0x1E, make_span(&parameter, 1));
+  if (!result) {
+    sleep(generateEcdsaSignatureTimeMs);
+    uint_least8_t response[1 + 2 * Scalar::size];
+    result = readFixedLengthResponse(response);
+    if (!result) {
+      result = convertResultByte(response[0]);
+      const uint_least8_t * begin = response + 1;
+      const uint_least8_t * 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 DS2476::computeSha2UniqueSecret(SecretNum msecretNum) {
+  uint_least8_t buffer = msecretNum << 4;
+  error_code result = writeCommand(0x55, make_span(&buffer, 1));
+  if (!result) {
+    sleep(sha256ComputationTimeMs);
+    result = readFixedLengthResponse(make_span(&buffer, 1));
+    if (!result) {
+      convertResultByte(buffer);
+    }
+  }
+  return result;
+}
+
+error_code DS2476::computeSha2Hmac(Page::span hmac) {
+  error_code result = writeCommand(0x2D);
+  if (!result) {
+    sleep(sha256ComputationTimeMs);
+    array<uint_least8_t, 1 + Page::size> response;
+    result = readFixedLengthResponse(response);
+    if (!result) {
+      result = convertResultByte(response[0]);
+      copy(response.begin() + 1, response.end(), hmac.begin());
+    }
+  }
+  return result;
+}
+
+error_code computeMultiblockHash(DS28C36 & ds28c36,
+                                 span<const uint_least8_t> data) {
+  error_code result;
+  span<const uint_least8_t>::index_type dataIdx = 0;
+  while (dataIdx < data.size() && !result) {
+    const span<const uint_least8_t>::index_type remainingSize =
+        data.size() - dataIdx;
+    const span<const uint_least8_t>::index_type chunkSize =
+        std::min<span<const uint_least8_t>::index_type>(remainingSize, 64);
+    result =
+        ds28c36.computeMultiblockHash(dataIdx == 0, remainingSize == chunkSize,
+                                      data.subspan(dataIdx, chunkSize));
+    dataIdx += chunkSize;
+  }
+  return result;
+}
+
+error_code verifyEcdsaSignature(DS28C36 & ds28c36, DS28C36::KeyNum publicKey,
+                                span<const uint_least8_t> data,
+                                Signature::const_span signature,
+                                DS28C36::PioState pioa,
+                                DS28C36::PioState piob) {
+  error_code result = computeMultiblockHash(ds28c36, data);
+  if (!result) {
+    result = ds28c36.verifyEcdsaSignature(publicKey, DS28C36::THASH, signature,
+                                          pioa, piob);
+  }
+  return result;
+}
+
+error_code verifyEcdsaSignature(DS28C36 & ds28c36,
+                                PublicKey::const_span publicKey,
+                                span<const uint_least8_t> data,
+                                Signature::const_span signature,
+                                DS28C36::PioState pioa,
+                                DS28C36::PioState piob) {
+  error_code result =
+      ds28c36.writeMemory(DS28C36::publicKeySxPage, publicKey.x);
+  if (!result) {
+    result = ds28c36.writeMemory(DS28C36::publicKeySyPage, publicKey.y);
+  }
+  if (!result) {
+    result = verifyEcdsaSignature(ds28c36, DS28C36::KeyNumS, data, signature,
+                                  pioa, piob);
+  }
+  return result;
+}
+
+error_code readRomIdAndManId(DS28C36 & ds28c36, RomId::span romId,
+                             ManId::span manId) {
+  DS28C36::Page::array page;
+  error_code result = ds28c36.readMemory(DS28C36::romOptionsPage, page);
+  if (!result) {
+    const DS28C36::RomOptions romOptions(page);
+    copy(romOptions.romId(), romId);
+    copy(romOptions.manId(), manId);
+  }
+  return result;
+}
+
+error_code enableCoprocessor(DS2476 & ds2476) {
+  DS2476::Page::array page;
+  error_code result = ds2476.readMemory(DS2476::gpioControlPage, page);
+  if (!result) {
+    DS2476::GpioControl gpioControl(page);
+    if (!gpioControl.pioaConducting()) {
+      gpioControl.setPioaConducting(true);
+      result = ds2476.writeMemory(DS2476::gpioControlPage, page);
+    }
+  }
+  return result;
+}
+
+error_code enableRomId(DS2476 & ds2476) {
+  DS2476::Page::array page;
+  error_code result = ds2476.readMemory(DS2476::romOptionsPage, page);
+  if (!result) {
+    DS2476::RomOptions romOptions(page);
+    if (!romOptions.romBlockDisable()) {
+      romOptions.setRomBlockDisable(true);
+      result = ds2476.writeMemory(DS2476::romOptionsPage, page);
+    }
+  }
+  return result;
+}
+
+static void setAnonymous(RomId::span romId) {
+  std::fill(romId.begin(), romId.end(), 0xFF);
+}
+
+DS28C36::PageAuthenticationData &
+DS28C36::PageAuthenticationData::setAnonymousRomId() {
+  setAnonymous(romId());
+  return *this;
+}
+
+DS28C36::EncryptionHmacData & DS28C36::EncryptionHmacData::setAnonymousRomId() {
+  setAnonymous(romId());
+  return *this;
+}
+
+} // namespace MaximInterfaceDevices
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS28C36_DS2476.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,944 @@
+/*******************************************************************************
+* 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 MaximInterfaceDevices_DS28C36_DS2476
+#define MaximInterfaceDevices_DS28C36_DS2476
+
+#include <stdint.h>
+#include <vector>
+#include <MaximInterfaceCore/Algorithm.hpp>
+#include <MaximInterfaceCore/array_span.hpp>
+#include <MaximInterfaceCore/Ecc256.hpp>
+#include <MaximInterfaceCore/FlagSet.hpp>
+#include <MaximInterfaceCore/I2CMaster.hpp>
+#include <MaximInterfaceCore/ManId.hpp>
+#include <MaximInterfaceCore/RomId.hpp>
+#include <MaximInterfaceCore/Sleep.hpp>
+#include <MaximInterfaceCore/system_error.hpp>
+#include "Config.hpp"
+
+namespace MaximInterfaceDevices {
+
+/// 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.
+  };
+
+  /// @name Device memory pages
+  /// @{
+
+  static const int publicKeyAxPage = 16;
+  static const int publicKeyAyPage = 17;
+  static const int publicKeyBxPage = 18;
+  static const int publicKeyByPage = 19;
+  static const int publicKeyCxPage = 20;
+  static const int publicKeyCyPage = 21;
+  static const int privateKeyAPage = 22;
+  static const int privateKeyBPage = 23;
+  static const int privateKeyCPage = 24;
+  static const int secretAPage = 25;
+  static const int secretBPage = 26;
+  static const int decrementCounterPage = 27;
+  static const int romOptionsPage = 28;
+  static const int gpioControlPage = 29;
+  static const int publicKeySxPage = 30;
+  static const int publicKeySyPage = 31;
+
+  /// @}
+
+  /// Number of memory pages on the device.
+  static const int memoryPages = 32;
+
+  /// 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 Core::array_span<uint_least8_t, 32> Page;
+
+  // Format page authentication input data.
+  class PageAuthenticationData;
+
+  // Format authenticated write input data.
+  class WriteAuthenticationData;
+
+  // Format compute secret input data.
+  class ComputeSecretData;
+
+  // Format encryption or decryption HMAC input data.
+  class EncryptionHmacData;
+
+  // Access fields in the ROM Options page.
+  class RomOptions;
+
+  // Access fields in the GPIO Control page.
+  class GpioControl;
+
+  /// 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 Core::FlagSet<PageProtectionType, 8> PageProtection;
+
+  /// Challenge for an encrypted device memory page.
+  typedef Core::array_span<uint_least8_t, 8> EncryptionChallenge;
+
+  DS28C36(Core::Sleep & sleep, Core::I2CMaster & master,
+          uint_least8_t address = 0x36)
+      : sleep_(&sleep), master(&master), address_(address & 0xFE) {}
+
+  void setSleep(Core::Sleep & sleep) { sleep_ = &sleep; }
+
+  void setMaster(Core::I2CMaster & master) { this->master = &master; }
+
+  uint_least8_t address() const { return address_; }
+
+  void setAddress(uint_least8_t address) { address_ = address & 0xFE; }
+
+  /// @brief Write memory with no protection.
+  /// @param pageNum Number of page to write.
+  /// @param page Data to write.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeMemory(int pageNum, Page::const_span page);
+
+  /// @brief Read memory with no protection.
+  /// @param pageNum Number of page to read.
+  /// @param[out] page Data that was read.
+  MaximInterfaceDevices_EXPORT Core::error_code readMemory(int pageNum,
+                                                           Page::span page);
+
+  /// @brief Write the temporary buffer.
+  /// @param data Data to write.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeBuffer(Core::span<const uint_least8_t> data);
+
+  /// @brief Read the temporary buffer.
+  /// @param[out] data Data that was read.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readBuffer(std::vector<uint_least8_t> & data);
+
+  /// @brief Read the protection settings of a page.
+  /// @param pageNum Number of page to read.
+  /// @param[out] protection Protection that was read.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readPageProtection(int pageNum, PageProtection & protection);
+
+  /// @brief Set the protection settings of a page.
+  /// @param pageNum Number of page to write.
+  /// @param protection Protection to write.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  setPageProtection(int pageNum, const PageProtection & protection);
+
+  /// Decrement the decrement-only counter.
+  MaximInterfaceDevices_EXPORT Core::error_code decrementCounter();
+
+  /// @brief Read a block of random data from the RNG.
+  /// @param[out] data Random data from RNG with length from 1 to 64.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readRng(Core::span<uint_least8_t> data);
+
+  /// @brief Read memory with encryption.
+  /// @param pageNum Number of page to read from.
+  /// @param secretNum Secret to use for encryption.
+  /// @param[out] challenge Encryption challenge that was read.
+  /// @param[out] data Encrypted page data that was read.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  encryptedReadMemory(int pageNum, SecretNum secretNum,
+                      EncryptionChallenge::span challenge, Page::span data);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeAndReadPageAuthentication(int pageNum, KeyNum keyNum,
+                                   Core::Ecc256::Signature::span signature);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeAndReadPageAuthentication(int pageNum, SecretNum secretNum,
+                                   Page::span hmac);
+
+  /// @brief Write with SHA2 authentication.
+  /// @param pageNum Number of page to write.
+  /// @param secretNum Secret to use for authentication.
+  /// @param page Data to write.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  authenticatedSha2WriteMemory(int pageNum, SecretNum secretNum,
+                               Page::const_span page);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeAndLockSha2Secret(int pageNum, SecretNum msecretNum,
+                           SecretNum dsecretNum, bool writeProtectEnable);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  generateEcc256KeyPair(KeyNum keyNum, bool writeProtectEnable);
+
+  /// @brief 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. Should be 64 bytes unless this is the last block.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeMultiblockHash(bool firstBlock, bool lastBlock,
+                        Core::span<const uint_least8_t> data);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  verifyEcdsaSignature(KeyNum keyNum, HashType hashType,
+                       Core::Ecc256::Signature::const_span signature,
+                       PioState pioa = Unchanged, PioState piob = Unchanged);
+
+  /// @brief
+  /// 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  authenticateEcdsaPublicKey(bool authWrites, bool ecdh, KeyNum keyNum,
+                             int csOffset,
+                             Core::Ecc256::Signature::const_span signature);
+
+  /// @brief Write with ECDSA authentication.
+  /// @param pageNum Number of page to write.
+  /// @param page Data to write.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  authenticatedEcdsaWriteMemory(int pageNum, Page::const_span page);
+
+  MaximInterfaceDevices_EXPORT static const Core::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;
+
+  Core::error_code writeCommand(uint_least8_t command,
+                                Core::span<const uint_least8_t> parameters);
+
+  Core::error_code writeCommand(uint_least8_t command) {
+    return writeCommand(command, Core::span<const uint_least8_t>());
+  }
+
+  Core::error_code
+  readVariableLengthResponse(Core::span<uint_least8_t> & response);
+
+  Core::error_code readFixedLengthResponse(Core::span<uint_least8_t> response);
+
+  void sleep(int ms) const { sleep_->invoke(ms); }
+
+private:
+  enum AuthType {
+    HmacWithSecretA = 0,
+    HmacWithSecretB = 1,
+    HmacWithSecretS = 2,
+    EcdsaWithKeyA = 3,
+    EcdsaWithKeyB = 4,
+    EcdsaWithKeyC = 5
+  };
+
+  const Core::Sleep * sleep_;
+  Core::I2CMaster * master;
+  uint_least8_t address_;
+
+  Core::error_code computeAndReadPageAuthentication(int pageNum,
+                                                    AuthType authType);
+};
+
+/// Interface to the DS2476 coprocessor.
+class DS2476 : public DS28C36 {
+public:
+  DS2476(Core::Sleep & sleep, Core::I2CMaster & master,
+         uint_least8_t address = 0x76)
+      : DS28C36(sleep, master, address) {}
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  generateEcdsaSignature(KeyNum keyNum,
+                         Core::Ecc256::Signature::span signature);
+
+  /// @brief Compute unique SHA2 secret.
+  /// @param msecretNum Master secret to use in computation.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeSha2UniqueSecret(SecretNum msecretNum);
+
+  /// @brief Compute SHA2 HMAC.
+  /// @param[out] hmac Computed HMAC.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeSha2Hmac(Page::span hmac);
+};
+
+inline Core::error_code make_error_code(DS28C36::ErrorValue e) {
+  return Core::error_code(e, DS28C36::errorCategory());
+}
+
+/// @brief
+/// Hash arbitrary length data with successive Compute Multiblock Hash commands.
+/// @param ds28c36 Device for computation.
+/// @param data Data to hash.
+MaximInterfaceDevices_EXPORT Core::error_code
+computeMultiblockHash(DS28C36 & ds28c36, Core::span<const uint_least8_t> data);
+
+/// @brief Verify ECDSA signature.
+/// @param ds28c36 Device for computation.
+/// @param publicKey Public key to use for verification.
+/// @param data 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.
+MaximInterfaceDevices_EXPORT Core::error_code
+verifyEcdsaSignature(DS28C36 & ds28c36, DS28C36::KeyNum publicKey,
+                     Core::span<const uint_least8_t> data,
+                     Core::Ecc256::Signature::const_span signature,
+                     DS28C36::PioState pioa = DS28C36::Unchanged,
+                     DS28C36::PioState piob = DS28C36::Unchanged);
+
+/// @brief Verify ECDSA signature.
+/// @param ds28c36 Device for computation.
+/// @param publicKey
+/// Public key to use for verification which is loaded into Public Key S.
+/// @param data 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.
+MaximInterfaceDevices_EXPORT Core::error_code
+verifyEcdsaSignature(DS28C36 & ds28c36,
+                     Core::Ecc256::PublicKey::const_span publicKey,
+                     Core::span<const uint_least8_t> data,
+                     Core::Ecc256::Signature::const_span signature,
+                     DS28C36::PioState pioa = DS28C36::Unchanged,
+                     DS28C36::PioState piob = DS28C36::Unchanged);
+
+/// @brief
+/// Read the device ROM ID and MAN ID using the Read Memory command on the
+/// ROM Options page.
+/// @param ds28c36 Device to read.
+/// @param[out] romId Read ROM ID valid when operation is successful.
+/// @param[out] manId Read MAN ID valid when operation is successful.
+MaximInterfaceDevices_EXPORT Core::error_code
+readRomIdAndManId(DS28C36 & ds28c36, Core::RomId::span romId,
+                  Core::ManId::span manId);
+
+/// @brief
+/// Enable coprocessor functionality on the DS2476 by writing to the
+/// GPIO Control page.
+MaximInterfaceDevices_EXPORT Core::error_code
+enableCoprocessor(DS2476 & ds2476);
+
+/// @brief
+/// Disable blocking of the ROM ID on the DS2476 by writing to the
+/// ROM Options page.
+MaximInterfaceDevices_EXPORT Core::error_code enableRomId(DS2476 & ds2476);
+
+/// Format page authentication input data.
+class DS28C36::PageAuthenticationData {
+public:
+  typedef Core::array_span<uint_least8_t, Core::RomId::size + 2 * Page::size +
+                                              1 + Core::ManId::size>
+      Result;
+
+  PageAuthenticationData() : result_() {}
+
+  /// Formatted data result.
+  Result::const_span result() const { return result_; }
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() {
+    return make_span(result_).subspan<romIdIdx, Core::RomId::size>();
+  }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const {
+    return const_cast<PageAuthenticationData &>(*this).romId();
+  }
+
+  /// Set ROM ID.
+  PageAuthenticationData & setRomId(Core::RomId::const_span romId) {
+    copy(romId, this->romId());
+    return *this;
+  }
+
+  /// Set ROM ID for use in anonymous mode.
+  MaximInterfaceDevices_EXPORT PageAuthenticationData & setAnonymousRomId();
+
+  /// @}
+
+  /// @name Page
+  /// @brief Data from a device memory page.
+  /// @{
+
+  /// Get mutable page.
+  Page::span page() {
+    return make_span(result_).subspan<pageIdx, Page::size>();
+  }
+
+  /// Get immutable page.
+  Page::const_span page() const {
+    return const_cast<PageAuthenticationData &>(*this).page();
+  }
+
+  /// Set page.
+  PageAuthenticationData & setPage(Page::const_span page) {
+    copy(page, this->page());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Challenge
+  /// @brief Random challenge used to prevent replay attacks.
+  /// @{
+
+  /// Get mutable Challenge.
+  Page::span challenge() {
+    return make_span(result_).subspan<challengeIdx, Page::size>();
+  }
+
+  /// Get immutable Challenge.
+  Page::const_span challenge() const {
+    return const_cast<PageAuthenticationData &>(*this).challenge();
+  }
+
+  /// Set Challenge.
+  PageAuthenticationData & setChallenge(Page::const_span challenge) {
+    copy(challenge, this->challenge());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Number of the page to use data from.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return result_[pageNumIdx]; }
+
+  /// Set page number.
+  PageAuthenticationData & setPageNum(int pageNum) {
+    result_[pageNumIdx] = pageNum;
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() {
+    return make_span(result_).subspan<manIdIdx, Core::ManId::size>();
+  }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const {
+    return const_cast<PageAuthenticationData &>(*this).manId();
+  }
+
+  /// Set MAN ID.
+  PageAuthenticationData & setManId(Core::ManId::const_span manId) {
+    copy(manId, this->manId());
+    return *this;
+  }
+
+  /// @}
+
+private:
+  typedef Result::span::index_type index;
+
+  static const index romIdIdx = 0;
+  static const index pageIdx = romIdIdx + Core::RomId::size;
+  static const index challengeIdx = pageIdx + Page::size;
+  static const index pageNumIdx = challengeIdx + Page::size;
+  static const index manIdIdx = pageNumIdx + 1;
+
+  Result::array result_;
+};
+
+/// Format authenticated write input data.
+class DS28C36::WriteAuthenticationData {
+public:
+  typedef PageAuthenticationData::Result Result;
+
+  WriteAuthenticationData() : data() {}
+
+  /// Formatted data result.
+  Result::const_span result() const { return data.result(); }
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() { return data.romId(); }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const { return data.romId(); }
+
+  /// Set ROM ID.
+  WriteAuthenticationData & setRomId(Core::RomId::const_span romId) {
+    data.setRomId(romId);
+    return *this;
+  }
+
+  /// Set ROM ID for use in anonymous mode.
+  WriteAuthenticationData & setAnonymousRomId() {
+    data.setAnonymousRomId();
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Old page
+  /// @brief Existing data contained in the page.
+  /// @{
+
+  /// Get mutable old page.
+  Page::span oldPage() { return data.page(); }
+
+  /// Get immutable old page.
+  Page::const_span oldPage() const { return data.page(); }
+
+  /// Set old page.
+  WriteAuthenticationData & setOldPage(Page::const_span oldPage) {
+    data.setPage(oldPage);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name New page
+  /// @brief New data to write to the page.
+  /// @{
+
+  /// Get mutable new page.
+  Page::span newPage() { return data.challenge(); }
+
+  /// Get immutable new page.
+  Page::const_span newPage() const { return data.challenge(); }
+
+  /// Set new page.
+  WriteAuthenticationData & setNewPage(Page::const_span newPage) {
+    data.setChallenge(newPage);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Page number for write operation.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return data.pageNum(); }
+
+  /// Set page number.
+  WriteAuthenticationData & setPageNum(int pageNum) {
+    data.setPageNum(pageNum);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() { return data.manId(); }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const { return data.manId(); }
+
+  /// Set MAN ID.
+  WriteAuthenticationData & setManId(Core::ManId::const_span manId) {
+    data.setManId(manId);
+    return *this;
+  }
+
+  /// @}
+
+private:
+  PageAuthenticationData data;
+};
+
+/// Format compute secret input data.
+class DS28C36::ComputeSecretData {
+public:
+  typedef PageAuthenticationData::Result Result;
+
+  ComputeSecretData() : data() {}
+
+  /// Formatted data result.
+  Result::const_span result() const { return data.result(); }
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() { return data.romId(); }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const { return data.romId(); }
+
+  /// Set ROM ID.
+  ComputeSecretData & setRomId(Core::RomId::const_span romId) {
+    data.setRomId(romId);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Binding Data
+  /// @brief Binding Data contained in the selected page.
+  /// @{
+
+  /// Get mutable Binding Data.
+  Page::span bindingData() { return data.page(); }
+
+  /// Get immutable Binding Data.
+  Page::const_span bindingData() const { return data.page(); }
+
+  /// Set Binding Data.
+  ComputeSecretData & setBindingData(Page::const_span bindingData) {
+    data.setPage(bindingData);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Partial Secret
+  /// @brief Partial Secret used for customization.
+  /// @{
+
+  /// Get mutable Partial Secret.
+  Page::span partialSecret() { return data.challenge(); }
+
+  /// Get immutable Partial Secret.
+  Page::const_span partialSecret() const { return data.challenge(); }
+
+  /// Set Partial Secret.
+  ComputeSecretData & setPartialSecret(Page::const_span partialSecret) {
+    data.setChallenge(partialSecret);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Page number for Binding Data.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return data.pageNum(); }
+
+  /// Set page number.
+  ComputeSecretData & setPageNum(int pageNum) {
+    data.setPageNum(pageNum);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() { return data.manId(); }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const { return data.manId(); }
+
+  /// Set MAN ID.
+  ComputeSecretData & setManId(Core::ManId::const_span manId) {
+    data.setManId(manId);
+    return *this;
+  }
+
+  /// @}
+
+private:
+  PageAuthenticationData data;
+};
+
+/// Format encryption or decryption HMAC input data.
+class DS28C36::EncryptionHmacData {
+public:
+  typedef Core::array_span<uint_least8_t, EncryptionChallenge::size +
+                                              Core::RomId::size + 1 +
+                                              Core::ManId::size>
+      Result;
+
+  EncryptionHmacData() : result_() {}
+
+  /// Formatted data result.
+  Result::const_span result() const { return result_; }
+
+  /// @name Encryption Challenge
+  /// @brief Random challenge used to prevent replay attacks.
+  /// @{
+
+  /// Get mutable Encryption Challenge.
+  EncryptionChallenge::span encryptionChallenge() {
+    return make_span(result_)
+        .subspan<encryptionChallengeIdx, EncryptionChallenge::size>();
+  }
+
+  /// Get immutable Encryption Challenge.
+  EncryptionChallenge::const_span encryptionChallenge() const {
+    return const_cast<EncryptionHmacData &>(*this).encryptionChallenge();
+  }
+
+  /// Set Encryption Challenge.
+  EncryptionHmacData &
+  setEncryptionChallenge(EncryptionChallenge::const_span encryptionChallenge) {
+    copy(encryptionChallenge, this->encryptionChallenge());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() {
+    return make_span(result_).subspan<romIdIdx, Core::RomId::size>();
+  }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const {
+    return const_cast<EncryptionHmacData &>(*this).romId();
+  }
+
+  /// Set ROM ID.
+  EncryptionHmacData & setRomId(Core::RomId::const_span romId) {
+    copy(romId, this->romId());
+    return *this;
+  }
+
+  /// Set ROM ID for use in anonymous mode.
+  MaximInterfaceDevices_EXPORT EncryptionHmacData & setAnonymousRomId();
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Number of the page to use data from.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return result_[pageNumIdx]; }
+
+  /// Set page number.
+  EncryptionHmacData & setPageNum(int pageNum) {
+    result_[pageNumIdx] = pageNum;
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() {
+    return make_span(result_).subspan<manIdIdx, Core::ManId::size>();
+  }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const {
+    return const_cast<EncryptionHmacData &>(*this).manId();
+  }
+
+  /// Set MAN ID.
+  EncryptionHmacData & setManId(Core::ManId::const_span manId) {
+    copy(manId, this->manId());
+    return *this;
+  }
+
+  /// @}
+
+private:
+  typedef Result::span::index_type index;
+
+  static const index encryptionChallengeIdx = 0;
+  static const index romIdIdx =
+      encryptionChallengeIdx + EncryptionChallenge::size;
+  static const index pageNumIdx = romIdIdx + Core::RomId::size;
+  static const index manIdIdx = pageNumIdx + 1;
+
+  Result::array result_;
+};
+
+/// Access fields in the ROM Options page.
+class DS28C36::RomOptions {
+public:
+  explicit RomOptions(Page::span page) : page(page) {}
+
+  bool romBlockDisable() const {
+    return page[romBlockDisableIdx] == enabledValue;
+  }
+
+  RomOptions & setRomBlockDisable(bool romBlockDisable) {
+    page[romBlockDisableIdx] = (romBlockDisable ? enabledValue : 0);
+    return *this;
+  }
+
+  bool anonymous() const { return page[anonymousIdx] == enabledValue; }
+
+  RomOptions & setAnonymous(bool anonymous) {
+    page[anonymousIdx] = (anonymous ? enabledValue : 0);
+    return *this;
+  }
+
+  Core::ManId::const_span manId() const {
+    return page.subspan<22, Core::ManId::size>();
+  }
+
+  Core::RomId::const_span romId() const {
+    return page.subspan<24, Core::RomId::size>();
+  }
+
+private:
+  static const Page::span::index_type romBlockDisableIdx = 0;
+  static const Page::span::index_type anonymousIdx = 1;
+  static const Page::span::value_type enabledValue = 0xAA;
+
+  Page::span page;
+};
+
+/// Access fields in the GPIO Control page.
+class DS28C36::GpioControl {
+public:
+  explicit GpioControl(Page::span page) : page(page) {}
+
+  bool pioaConducting() const {
+    return page[pioaConductingIdx] == pioConductingValue;
+  }
+
+  GpioControl & setPioaConducting(bool pioaConducting) {
+    page[pioaConductingIdx] = (pioaConducting ? pioConductingValue : 0x55);
+    return *this;
+  }
+
+  bool piobConducting() const {
+    return page[piobConductingIdx] == pioConductingValue;
+  }
+
+  GpioControl & setPiobConducting(bool piobConducting) {
+    page[piobConductingIdx] = (piobConducting ? pioConductingValue : 0x55);
+    return *this;
+  }
+
+  bool pioaLevel() const { return page[2] == pioLevelValue; }
+
+  bool piobLevel() const { return page[3] == pioLevelValue; }
+
+private:
+  static const Page::span::index_type pioaConductingIdx = 0;
+  static const Page::span::index_type piobConductingIdx = 1;
+  static const Page::span::value_type pioConductingValue = 0xAA;
+  static const Page::span::value_type pioLevelValue = 0x55;
+
+  Page::span page;
+};
+
+} // namespace MaximInterfaceDevices
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS28C39.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,341 @@
+/*******************************************************************************
+* Copyright (C) 2018 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 <algorithm>
+#include <MaximInterfaceCore/Error.hpp>
+#include "DS28C39.hpp"
+
+namespace MaximInterfaceDevices {
+
+using namespace Core;
+using std::copy;
+
+static const int readMemoryTimeMs = 30;
+static const int writeMemoryTimeMs = 65;
+static const int writeStateTimeMs = 15;
+static const int generateEccKeyPairTimeMs = 200;
+static const int generateEcdsaSignatureTimeMs = 130;
+static const int trngOnDemandCheckTimeMs = 20;
+static const int trngGenerationTimeMs = 10;
+static const int verifyEcdsaSignatureTimeMs = 180;
+
+const int DS28C39::authorityPublicKeyXPage;
+const int DS28C39::authorityPublicKeyYPage;
+const int DS28C39::writePublicKeyXPage;
+const int DS28C39::writePublicKeyYPage;
+const int DS28C39::memoryPages;
+
+error_code DS28C39::writeMemory(int pageNum, Page::const_span page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t request[2 + Page::size];
+  request[0] = 0x96;
+  request[1] = pageNum;
+  copy(page.begin(), page.end(), request + 2);
+  return runCommand(request, writeMemoryTimeMs);
+}
+
+error_code DS28C39::readMemory(int pageNum, Page::span page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[1 + Page::size];
+  buffer[0] = 0x44;
+  buffer[1] = pageNum;
+  span<uint_least8_t> response(buffer);
+  const error_code result =
+      runCommand(make_span(buffer, 2), readMemoryTimeMs, response);
+  if (!result) {
+    copy(response.begin(), response.end(), page.begin());
+  }
+  return result;
+}
+
+error_code DS28C39::readStatus(bool entropyHealthTest, Status & status) {
+  int delay = readMemoryTimeMs;
+  if (entropyHealthTest) {
+    delay += trngOnDemandCheckTimeMs;
+  }
+  uint_least8_t buffer[Status::PageProtectionList::csize + RomId::size +
+                       ManId::size + Status::RomVersion::csize + 2];
+  buffer[0] = 0xAA;
+  buffer[1] = entropyHealthTest ? 0x01 : 0x00;
+  span<uint_least8_t> response(buffer);
+  error_code result = runCommand(make_span(buffer, 2), delay, response);
+  if (!result) {
+    span<uint_least8_t>::const_iterator responseIt = response.begin();
+    for (Status::PageProtectionList::iterator it =
+             status.pageProtection.begin();
+         it != status.pageProtection.end(); ++it) {
+      *it = *responseIt;
+      ++responseIt;
+    }
+    span<uint_least8_t>::const_iterator responseItEnd =
+        responseIt + status.romId.size();
+    copy(responseIt, responseItEnd, status.romId.begin());
+    responseIt = responseItEnd;
+    responseItEnd = responseIt + status.manId.size();
+    copy(responseIt, responseItEnd, status.manId.begin());
+    responseIt = responseItEnd;
+    responseItEnd = responseIt + status.romVersion.size();
+    copy(responseIt, responseItEnd, status.romVersion.begin());
+    responseIt = responseItEnd;
+    switch (*responseIt) {
+    case Status::TestNotPerformed:
+    case Status::EntropyHealthy:
+    case Status::EntropyNotHealthy:
+      status.entropyHealthTestStatus =
+          static_cast<Status::EntropyHealthTestStatus>(*responseIt);
+      break;
+
+    default:
+      result = make_error_code(InvalidResponseError);
+      break;
+    }
+  }
+  return result;
+}
+
+error_code DS28C39::setPageProtection(int pageNum,
+                                      const PageProtection & protection) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const uint_least8_t request[] = {
+      0xC3, static_cast<uint_least8_t>(pageNum),
+      static_cast<uint_least8_t>(protection.to_ulong())};
+  return runCommand(request, writeStateTimeMs);
+}
+
+error_code
+DS28C39::computeAndReadPageAuthentication(int pageNum, bool anonymous,
+                                          Page::const_span challenge,
+                                          Ecc256::Signature::span signature) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const size_t requestSize = 2 + Page::size;
+  const size_t responseSize = 1 + 2 * Ecc256::Scalar::size;
+  uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
+  buffer[0] = 0xA5;
+  buffer[1] = pageNum | (anonymous ? 0xE0 : 0x00);
+  copy(challenge.begin(), challenge.end(), buffer + 2);
+  span<uint_least8_t> response(buffer, responseSize);
+  const error_code result = runCommand(make_span(buffer, requestSize),
+                                       generateEcdsaSignatureTimeMs, response);
+  if (!result) {
+    span<uint_least8_t>::const_iterator begin = response.begin();
+    span<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 DS28C39::disableDevice() {
+  const uint_least8_t request[] = {0x33, 0x9E, 0xA7, 0x49, 0xFB,
+                                   0x10, 0x62, 0x0A, 0x26};
+  return runCommand(request, writeStateTimeMs);
+}
+
+error_code
+DS28C39::readDevicePublicKey(Ecc256::PublicKey::span devicePublicKey) {
+  uint_least8_t buffer[1 + 2 * Ecc256::Scalar::size];
+  buffer[0] = 0xCB;
+  span<uint_least8_t> response(buffer);
+  const error_code result =
+      runCommand(make_span(buffer, 1), generateEccKeyPairTimeMs, response);
+  if (!result) {
+    span<uint_least8_t>::const_iterator begin = response.begin();
+    span<uint_least8_t>::const_iterator end = begin + devicePublicKey.x.size();
+    copy(begin, end, devicePublicKey.x.begin());
+    begin = end;
+    end = begin + devicePublicKey.y.size();
+    copy(begin, end, devicePublicKey.y.begin());
+  }
+  return result;
+}
+
+error_code DS28C39::readRng(span<uint_least8_t> data) {
+  const span<uint_least8_t>::index_type maxDataSize = 64;
+  if ((data.size() < 1) || (data.size() > maxDataSize)) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[1 + maxDataSize];
+  buffer[0] = 0xD2;
+  buffer[1] = static_cast<uint_least8_t>(data.size() - 1);
+  span<uint_least8_t> response(buffer, 1 + data.size());
+  const error_code result =
+      runCommand(make_span(buffer, 2), trngGenerationTimeMs, response);
+  if (!result) {
+    copy(response.begin(), response.end(), data.begin());
+  }
+  return result;
+}
+
+error_code
+DS28C39::authenticatePublicKey(Ecc256::Signature::const_span certificate,
+                               span<const uint_least8_t> customization) {
+  static const span<const uint_least8_t>::index_type maxCustomizationSize = 32;
+  static const span<const uint_least8_t>::index_type signatureSize =
+      2 * Ecc256::Scalar::size;
+
+  if (customization.size() < 1 || customization.size() > maxCustomizationSize) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t request[1 + signatureSize + maxCustomizationSize];
+  uint_least8_t * requestIt = request;
+  *requestIt++ = 0x59;
+  requestIt = copy(certificate.r.begin(), certificate.r.end(), requestIt);
+  requestIt = copy(certificate.s.begin(), certificate.s.end(), requestIt);
+  requestIt = copy(customization.begin(), customization.end(), requestIt);
+  return runCommand(make_span(request, requestIt), verifyEcdsaSignatureTimeMs);
+}
+
+error_code
+DS28C39::authenticatedWriteMemory(int pageNum, Page::const_span page,
+                                  Ecc256::Signature::const_span signature) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t request[2 + Page::size + 2 * Ecc256::Scalar::size];
+  uint_least8_t * requestIt = request;
+  *requestIt++ = 0x89;
+  *requestIt++ = pageNum;
+  requestIt = copy(page.begin(), page.end(), requestIt);
+  requestIt = copy(signature.r.begin(), signature.r.end(), requestIt);
+  copy(signature.s.begin(), signature.s.end(), requestIt);
+  return runCommand(request, verifyEcdsaSignatureTimeMs + writeMemoryTimeMs);
+}
+
+error_code DS28C39::runCommand(span<const uint_least8_t> request, int delayTime,
+                               span<uint_least8_t> & response) {
+  const span<const uint_least8_t>::index_type responseInputSize =
+      response.size();
+  error_code result = doRunCommand(request, delayTime, response);
+  if (result) {
+    return result;
+  }
+  if (response.empty()) {
+    return make_error_code(InvalidResponseError);
+  }
+  // Parse command result byte.
+  switch (response[0]) {
+  case 0xAA:
+    // Success response.
+    if (response.size() != responseInputSize) {
+      result = make_error_code(InvalidResponseError);
+    }
+    break;
+
+  case 0x00:
+    result = make_error_code(AuthenticationError);
+    break;
+
+  default:
+    result.assign(response[0], errorCategory());
+    break;
+  }
+  response = response.subspan(1);
+  return result;
+}
+
+error_code DS28C39::runCommand(span<const uint_least8_t> request,
+                               int delayTime) {
+  uint_least8_t buffer;
+  span<uint_least8_t> response(&buffer, 1);
+  return runCommand(request, delayTime, response);
+}
+
+const error_category & DS28C39::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "DS28C39"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case InvalidOperationError:
+        return "Invalid Operation Error";
+
+      case InvalidParameterError:
+        return "Invalid Parameter Error";
+
+      case InvalidSequenceError:
+        return "Invalid Sequence Error";
+
+      case InternalError:
+        return "Internal Error";
+
+      case DeviceDisabledError:
+        return "Device Disabled Error";
+
+      case AuthenticationError:
+        return "Authentication Error";
+
+      case InvalidResponseError:
+        return "Invalid Response Error";
+      }
+      return defaultErrorMessage(condition);
+    }
+  } instance;
+  return instance;
+}
+
+error_code readRomIdAndManId(DS28C39 & ds28c39, Core::RomId::span romId,
+                             Core::ManId::span manId) {
+  DS28C39::Status status;
+  const error_code result = ds28c39.readStatus(false, status);
+  if (!result) {
+    copy(make_span(status.romId), romId);
+    copy(make_span(status.manId), manId);
+  }
+  return result;
+}
+
+DS28C39::PageAuthenticationData &
+DS28C39::PageAuthenticationData::setAnonymousRomId() {
+  std::fill(romId().begin(), romId().end(), 0xFF);
+  return *this;
+}
+
+} // namespace MaximInterfaceDevices
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS28C39.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,444 @@
+/*******************************************************************************
+* Copyright (C) 2018 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 MaximInterfaceDevices_DS28C39
+#define MaximInterfaceDevices_DS28C39
+
+#include <stdint.h>
+#include <MaximInterfaceCore/Algorithm.hpp>
+#include <MaximInterfaceCore/array_span.hpp>
+#include <MaximInterfaceCore/Ecc256.hpp>
+#include <MaximInterfaceCore/FlagSet.hpp>
+#include <MaximInterfaceCore/ManId.hpp>
+#include <MaximInterfaceCore/RomId.hpp>
+#include <MaximInterfaceCore/RunCommand.hpp>
+#include <MaximInterfaceCore/system_error.hpp>
+#include "Config.hpp"
+
+namespace MaximInterfaceDevices {
+
+class DS28C39 {
+public:
+  /// Device command results.
+  enum ErrorValue {
+    InvalidOperationError = 0x55,
+    InvalidParameterError = 0x77,
+    InvalidSequenceError = 0x33,
+    InternalError = 0x22,
+    DeviceDisabledError = 0x88,
+    AuthenticationError = 0x100,
+    InvalidResponseError ///< Command response does not match expected format.
+  };
+
+  /// @name Device memory pages
+  /// @{
+
+  static const int authorityPublicKeyXPage = 5;
+  static const int authorityPublicKeyYPage = 6;
+  static const int writePublicKeyXPage = 7;
+  static const int writePublicKeyYPage = 8;
+
+  /// @}
+
+  static const int memoryPages = 9;
+
+  /// Holds a device memory page.
+  typedef Core::array_span<uint_least8_t, 32> Page;
+
+  // Format page authentication input data.
+  class PageAuthenticationData;
+
+  // Format authenticated write input data.
+  class WriteAuthenticationData;
+
+  /// Page protection types.
+  enum PageProtectionType {
+    RP = 0x01, ///< Read protection.
+    WP = 0x02, ///< Write protection.
+    EM = 0x04, ///< EPROM emulation mode.
+    ECW = 0x10 ///< Authenticated write.
+  };
+  typedef Core::FlagSet<PageProtectionType, 5> PageProtection;
+
+  struct Status {
+    enum EntropyHealthTestStatus {
+      TestNotPerformed = 0xFF,
+      EntropyHealthy = 0xAA,
+      EntropyNotHealthy = 0xDD
+    };
+
+    typedef Core::array<PageProtection, memoryPages - 2> PageProtectionList;
+    typedef Core::array<uint_least8_t, 2> RomVersion;
+
+    PageProtectionList pageProtection;
+    Core::RomId::array romId;
+    Core::ManId::array manId;
+    RomVersion romVersion;
+    EntropyHealthTestStatus entropyHealthTestStatus;
+  };
+
+  explicit DS28C39(const Core::RunCommand & runCommand)
+      : doRunCommand(runCommand) {}
+
+  void setRunCommand(const Core::RunCommand & runCommand) {
+    doRunCommand = runCommand;
+  }
+
+  /// @brief Write memory with no protection.
+  /// @param pageNum Number of page to write.
+  /// @param page Data to write.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeMemory(int pageNum, Page::const_span page);
+
+  /// @brief Read memory with no protection.
+  /// @param pageNum Number of page to read.
+  /// @param[out] page Data that was read.
+  MaximInterfaceDevices_EXPORT Core::error_code readMemory(int pageNum,
+                                                           Page::span page);
+
+  /// @brief
+  /// Reads the current status of the device and optionally performs an
+  /// entropy health test.
+  /// @param entropyHealthTest True to perform an entropy health test.
+  /// @param[out] status Status that was read.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readStatus(bool entropyHealthTest, Status & status);
+
+  /// @brief Set the protection settings of a page.
+  /// @param pageNum Number of page to write.
+  /// @param protection Protection to write.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  setPageProtection(int pageNum, const PageProtection & protection);
+
+  /// @brief Compute and read page authentication with ECDSA.
+  /// @param pageNum Number of page to authenticate.
+  /// @param anonymous True to disable use of ROM ID in computation.
+  /// @param challenge Random challenge used to prevent replay attacks.
+  /// @param[out] signature Computed page signature.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeAndReadPageAuthentication(int pageNum, bool anonymous,
+                                   Page::const_span challenge,
+                                   Core::Ecc256::Signature::span signature);
+
+  /// Permanently disable the device.
+  MaximInterfaceDevices_EXPORT Core::error_code disableDevice();
+
+  /// @brief Generate the device's ECDSA public key from the PUF private key.
+  /// @param[out] devicePublicKey Device Public Key
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readDevicePublicKey(Core::Ecc256::PublicKey::span devicePublicKey);
+
+  /// @brief Read a block of random data from the RNG.
+  /// @param[out] data Random data from RNG with length from 1 to 64.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readRng(Core::span<uint_least8_t> data);
+
+  /// @brief
+  /// Authenticate a public key for authenticated writes using the
+  /// Authority Public Key.
+  /// @param certificate
+  /// Certificate to use for authentication of the Write Public Key.
+  /// @param customization
+  /// Certificate customization with length from 1 to 32.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  authenticatePublicKey(Core::Ecc256::Signature::const_span certificate,
+                        Core::span<const uint_least8_t> customization);
+
+  /// @brief Write with ECDSA authentication using the Write Public Key.
+  /// @param pageNum Number of page to write.
+  /// @param page Data to write.
+  /// @param signature Signature to use for authentication of page data.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  authenticatedWriteMemory(int pageNum, Page::const_span page,
+                           Core::Ecc256::Signature::const_span signature);
+
+  MaximInterfaceDevices_EXPORT static const Core::error_category &
+  errorCategory();
+
+protected:
+  MaximInterfaceDevices_EXPORT Core::error_code
+  runCommand(Core::span<const uint_least8_t> request, int delayTime,
+             Core::span<uint_least8_t> & response);
+
+  MaximInterfaceDevices_EXPORT Core::error_code
+  runCommand(Core::span<const uint_least8_t> request, int delayTime);
+
+private:
+  Core::RunCommand doRunCommand;
+};
+
+inline Core::error_code make_error_code(DS28C39::ErrorValue e) {
+  return Core::error_code(e, DS28C39::errorCategory());
+}
+
+/// @brief Read the device ROM ID and MAN ID using the Read Status command.
+/// @param ds28c39 Device to read.
+/// @param[out] romId Read ROM ID valid when operation is successful.
+/// @param[out] manId Read MAN ID valid when operation is successful.
+MaximInterfaceDevices_EXPORT Core::error_code
+readRomIdAndManId(DS28C39 & ds28c39, Core::RomId::span romId,
+                  Core::ManId::span manId);
+
+/// Format page authentication input data.
+class DS28C39::PageAuthenticationData {
+public:
+  typedef Core::array_span<uint_least8_t, Core::RomId::size + 2 * Page::size +
+                                              1 + Core::ManId::size>
+      Result;
+
+  PageAuthenticationData() : result_() {}
+
+  /// Formatted data result.
+  Result::const_span result() const { return result_; }
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() {
+    return make_span(result_).subspan<romIdIdx, Core::RomId::size>();
+  }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const {
+    return const_cast<PageAuthenticationData &>(*this).romId();
+  }
+
+  /// Set ROM ID.
+  PageAuthenticationData & setRomId(Core::RomId::const_span romId) {
+    copy(romId, this->romId());
+    return *this;
+  }
+
+  /// Set ROM ID for use in anonymous mode.
+  MaximInterfaceDevices_EXPORT PageAuthenticationData & setAnonymousRomId();
+
+  /// @}
+
+  /// @name Page
+  /// @brief Data from a device memory page.
+  /// @{
+
+  /// Get mutable page.
+  Page::span page() {
+    return make_span(result_).subspan<pageIdx, Page::size>();
+  }
+
+  /// Get immutable page.
+  Page::const_span page() const {
+    return const_cast<PageAuthenticationData &>(*this).page();
+  }
+
+  /// Set page.
+  PageAuthenticationData & setPage(Page::const_span page) {
+    copy(page, this->page());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Challenge
+  /// @brief Random challenge used to prevent replay attacks.
+  /// @{
+
+  /// Get mutable Challenge.
+  Page::span challenge() {
+    return make_span(result_).subspan<challengeIdx, Page::size>();
+  }
+
+  /// Get immutable Challenge.
+  Page::const_span challenge() const {
+    return const_cast<PageAuthenticationData &>(*this).challenge();
+  }
+
+  /// Set Challenge.
+  PageAuthenticationData & setChallenge(Page::const_span challenge) {
+    copy(challenge, this->challenge());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Number of the page to use data from.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return result_[pageNumIdx]; }
+
+  /// Set page number.
+  PageAuthenticationData & setPageNum(int pageNum) {
+    result_[pageNumIdx] = pageNum;
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() {
+    return make_span(result_).subspan<manIdIdx, Core::ManId::size>();
+  }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const {
+    return const_cast<PageAuthenticationData &>(*this).manId();
+  }
+
+  /// Set MAN ID.
+  PageAuthenticationData & setManId(Core::ManId::const_span manId) {
+    copy(manId, this->manId());
+    return *this;
+  }
+
+  /// @}
+
+private:
+  typedef Result::span::index_type index;
+
+  static const index romIdIdx = 0;
+  static const index pageIdx = romIdIdx + Core::RomId::size;
+  static const index challengeIdx = pageIdx + Page::size;
+  static const index pageNumIdx = challengeIdx + Page::size;
+  static const index manIdIdx = pageNumIdx + 1;
+
+  Result::array result_;
+};
+
+/// Format authenticated write input data.
+class DS28C39::WriteAuthenticationData {
+public:
+  typedef PageAuthenticationData::Result Result;
+
+  WriteAuthenticationData() : data() { setPageNum(0); }
+
+  /// Formatted data result.
+  Result::const_span result() const { return data.result(); }
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() { return data.romId(); }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const { return data.romId(); }
+
+  /// Set ROM ID.
+  WriteAuthenticationData & setRomId(Core::RomId::const_span romId) {
+    data.setRomId(romId);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Old page
+  /// @brief Existing data contained in the page.
+  /// @{
+
+  /// Get mutable old page.
+  Page::span oldPage() { return data.page(); }
+
+  /// Get immutable old page.
+  Page::const_span oldPage() const { return data.page(); }
+
+  /// Set old page.
+  WriteAuthenticationData & setOldPage(Page::const_span oldPage) {
+    data.setPage(oldPage);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name New page
+  /// @brief New data to write to the page.
+  /// @{
+
+  /// Get mutable new page.
+  Page::span newPage() { return data.challenge(); }
+
+  /// Get immutable new page.
+  Page::const_span newPage() const { return data.challenge(); }
+
+  /// Set new page.
+  WriteAuthenticationData & setNewPage(Page::const_span newPage) {
+    data.setChallenge(newPage);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Page number for write operation.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return data.pageNum() & 0x7F; }
+
+  /// Set page number.
+  WriteAuthenticationData & setPageNum(int pageNum) {
+    data.setPageNum(pageNum | 0x80);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() { return data.manId(); }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const { return data.manId(); }
+
+  /// Set MAN ID.
+  WriteAuthenticationData & setManId(Core::ManId::const_span manId) {
+    data.setManId(manId);
+    return *this;
+  }
+
+  /// @}
+
+private:
+  PageAuthenticationData data;
+};
+
+} // namespace MaximInterfaceDevices
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS28C40.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,655 @@
+/*******************************************************************************
+* Copyright (C) 2019 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 <algorithm>
+#include <MaximInterfaceCore/Error.hpp>
+#include "DS28C40.hpp"
+
+namespace MaximInterfaceDevices {
+
+using namespace Core;
+using std::copy;
+
+static const int readMemoryTimeMs = 2;
+static const int writeMemoryTimeMs = 150;
+static const int writeStateTimeMs = 15;
+static const int generateEccKeyPairTimeMs = 500;
+static const int generateEcdsaSignatureTimeMs = 50;
+static const int computeTimeMs = 4;
+static const int verifyEcdsaTimeMs = 160;
+static const int trngGenerationTimeMs = 50;
+static const int trngOnDemandCheckTimeMs = 50;
+
+static const uint_least8_t computeAndReadPageAuthenticationCmd = 0xA5;
+static const uint_least8_t readRngCmd = 0xD2;
+
+const int DS28C40::publicKeyAxPage;
+const int DS28C40::publicKeyAyPage;
+const int DS28C40::publicKeyBxPage;
+const int DS28C40::publicKeyByPage;
+const int DS28C40::authorityPublicKeyAxPage;
+const int DS28C40::authorityPublicKeyAyPage;
+const int DS28C40::authorityPublicKeyBxPage;
+const int DS28C40::authorityPublicKeyByPage;
+const int DS28C40::privateKeyAPage;
+const int DS28C40::privateKeyBPage;
+const int DS28C40::secretAPage;
+const int DS28C40::secretBPage;
+const int DS28C40::romOptionsPage;
+const int DS28C40::gpioControlPage;
+const int DS28C40::publicKeySxPage;
+const int DS28C40::publicKeySyPage;
+
+const int DS28C40::memoryPages;
+const int DS28C40::protectionBlocks;
+
+error_code DS28C40::writeMemory(int pageNum, Page::const_span page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t request[2 + Page::size];
+  request[0] = 0x96;
+  request[1] = pageNum;
+  copy(page.begin(), page.end(), request + 2);
+  return runCommand(request, writeMemoryTimeMs);
+}
+
+error_code DS28C40::readMemory(int pageNum, Page::span page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[1 + Page::size];
+  buffer[0] = 0x44;
+  buffer[1] = pageNum;
+  span<uint_least8_t> response(buffer);
+  const error_code result =
+      runCommand(make_span(buffer, 2), readMemoryTimeMs, response);
+  if (!result) {
+    copy(response.begin(), response.end(), page.begin());
+  }
+  return result;
+}
+
+error_code
+DS28C40::encryptedReadMemory(int pageNum, KeySecret secret,
+                             EncryptionChallenge::span encryptionChallenge,
+                             Page::span encryptedPage) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const size_t requestSize = 3;
+  const size_t responseSize = 1 + EncryptionChallenge::size + Page::size;
+  uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
+  buffer[0] = 0x4B;
+  buffer[1] = pageNum;
+  buffer[2] = secret;
+  span<uint_least8_t> response(buffer, responseSize);
+  const error_code result =
+      runCommand(make_span(buffer, requestSize),
+                 readMemoryTimeMs + computeTimeMs, response);
+  if (!result) {
+    span<uint_least8_t>::const_iterator begin = response.begin();
+    span<uint_least8_t>::const_iterator end =
+        begin + encryptionChallenge.size();
+    copy(begin, end, encryptionChallenge.begin());
+    begin = end;
+    end = begin + encryptedPage.size();
+    copy(begin, end, encryptedPage.begin());
+  }
+  return result;
+}
+
+error_code DS28C40::readBlockProtection(int blockNumber,
+                                        Optional<KeySecret> & keySecret,
+                                        BlockProtection & protection) {
+  if (blockNumber < 0 || blockNumber >= protectionBlocks) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const size_t requestSize = 2;
+  const size_t responseSize = 3;
+  uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
+  buffer[0] = 0xAA;
+  buffer[1] = blockNumber;
+  span<uint_least8_t> response(buffer, responseSize);
+  const error_code result =
+      runCommand(make_span(buffer, requestSize), readMemoryTimeMs, response);
+  if (result) {
+    return result;
+  }
+  if ((response[0] & 0x3F) != blockNumber) {
+    return make_error_code(InvalidResponseError);
+  }
+  switch (response[0] >> 6) {
+  case 0:
+    keySecret = none;
+    break;
+  case 1:
+    keySecret = KeySecretA;
+    break;
+  case 2:
+    keySecret = KeySecretB;
+    break;
+  default:
+    return make_error_code(InvalidResponseError);
+  }
+  if ((response[1] & 0x20) != 0) {
+    return make_error_code(InvalidResponseError);
+  }
+  protection = response[1];
+  return error_code();
+}
+
+error_code DS28C40::setBlockProtection(int blockNum, KeySecret keySecret,
+                                       const BlockProtection & protection) {
+  if (blockNum < 0 || blockNum >= protectionBlocks || keySecret == KeySecretS) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const uint_least8_t request[] = {
+      0xC3,
+      static_cast<uint_least8_t>((keySecret == KeySecretB ? 0x80 : 0x40) |
+                                 blockNum),
+      static_cast<uint_least8_t>(protection.to_ulong())};
+  return runCommand(request, writeStateTimeMs);
+}
+
+error_code
+DS28C40::computeAndReadPageAuthentication(int pageNum, KeySecret key,
+                                          Page::const_span challenge,
+                                          Ecc256::Signature::span signature) {
+  if (pageNum < 0 || pageNum >= memoryPages || key == KeySecretS) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const size_t requestSize = 3 + Page::size;
+  const size_t responseSize = 1 + 2 * Ecc256::Scalar::size;
+  uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
+  buffer[0] = computeAndReadPageAuthenticationCmd;
+  buffer[1] = pageNum;
+  buffer[2] = key + 3;
+  copy(challenge.begin(), challenge.end(), buffer + 3);
+  span<uint_least8_t> response(buffer, responseSize);
+  const error_code result = runCommand(make_span(buffer, requestSize),
+                                       generateEcdsaSignatureTimeMs, response);
+  if (!result) {
+    span<uint_least8_t>::const_iterator begin = response.begin();
+    span<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 DS28C40::computeAndReadPageAuthentication(int pageNum,
+                                                     KeySecret secret,
+                                                     Page::const_span challenge,
+                                                     Page::span hmac) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const size_t requestSize = 3 + Page::size;
+  const size_t responseSize = 1 + Page::size;
+  uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
+  buffer[0] = computeAndReadPageAuthenticationCmd;
+  buffer[1] = pageNum;
+  buffer[2] = secret;
+  copy(challenge.begin(), challenge.end(), buffer + 3);
+  span<uint_least8_t> response(buffer, responseSize);
+  const error_code result =
+      runCommand(make_span(buffer, requestSize), computeTimeMs, response);
+  if (!result) {
+    copy(response.begin(), response.end(), hmac.begin());
+  }
+  return result;
+}
+
+error_code DS28C40::computeMultiblockHash(bool firstBlock, bool lastBlock,
+                                          span<const uint_least8_t> data) {
+  const span<const uint_least8_t>::index_type maxDataSize = 64;
+
+  if (data.size() < 1 || data.size() > maxDataSize) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[2 + maxDataSize];
+  buffer[0] = 0x33;
+  buffer[1] = 0;
+  if (firstBlock) {
+    buffer[1] |= 0x40;
+  }
+  if (lastBlock) {
+    buffer[1] |= 0x80;
+  }
+  copy(data.begin(), data.end(), buffer + 2);
+  return runCommand(make_span(buffer, 2 + data.size()), computeTimeMs);
+}
+
+error_code DS28C40::verifyEcdsaSignature(
+    KeySecret key, bool authorityKey, GpioState gpioState,
+    Ecc256::Signature::const_span signature, span<const uint_least8_t> data) {
+  return verifyEcdsaSignature(key, authorityKey, DataInput, gpioState,
+                              signature, data);
+}
+
+error_code DS28C40::verifyEcdsaSignature(
+    KeySecret key, bool authorityKey, GpioState gpioState,
+    Ecc256::Signature::const_span signature, Page::const_span hash) {
+  return verifyEcdsaSignature(key, authorityKey, HashInput, gpioState,
+                              signature, hash);
+}
+
+error_code
+DS28C40::verifyEcdsaSignature(KeySecret key, bool authorityKey,
+                              GpioState gpioState,
+                              Ecc256::Signature::const_span signature) {
+  return verifyEcdsaSignature(key, authorityKey, THASH, gpioState, signature,
+                              span<const uint_least8_t>());
+}
+
+error_code DS28C40::verifyEcdsaSignature(
+    KeySecret key, bool authorityKey, HashType hashType, GpioState gpioState,
+    Ecc256::Signature::const_span signature, span<const uint_least8_t> buffer) {
+  const span<const uint_least8_t>::index_type maxBufferSize = 61;
+
+  if (buffer.size() > maxBufferSize) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t request[2 + 2 * Ecc256::Scalar::size + maxBufferSize];
+  uint_least8_t * requestIt = request;
+  *requestIt++ = 0x59;
+  switch (key) {
+  case KeySecretA:
+    if (authorityKey) {
+      *requestIt = 2;
+    } else {
+      *requestIt = 0;
+    }
+    break;
+  case KeySecretB:
+    if (authorityKey) {
+      *requestIt = 3;
+    } else {
+      *requestIt = 1;
+    }
+    break;
+  case KeySecretS:
+    if (!authorityKey) {
+      *requestIt = 4;
+      break;
+    }
+    // else: Go to default case.
+  default:
+    return make_error_code(InvalidParameterError);
+  }
+  *requestIt |= hashType << 3;
+  if (gpioState != Unchanged) {
+    *requestIt |= 0x40;
+  }
+  if (gpioState == Conducting) {
+    *requestIt |= 0x20;
+  }
+  requestIt = copy(signature.r.begin(), signature.r.end(), ++requestIt);
+  requestIt = copy(signature.s.begin(), signature.s.end(), requestIt);
+  requestIt = copy(buffer.begin(), buffer.end(), requestIt);
+  return runCommand(make_span(request, requestIt),
+                    verifyEcdsaTimeMs +
+                        (hashType == DataInput ? computeTimeMs : 0));
+}
+
+error_code DS28C40::authenticateEcdsaPublicKey(
+    KeySecret key, Ecc256::Signature::const_span cert,
+    span<const uint_least8_t> certCustomization) {
+  return authenticateEcdsaPublicKey(key, true, cert, certCustomization, NULL);
+}
+
+error_code DS28C40::authenticateEcdsaPublicKey(
+    KeySecret key, bool authWrites, Ecc256::Signature::const_span cert,
+    span<const uint_least8_t> certCustomization,
+    span<const uint_least8_t> ecdhCustomization) {
+  return authenticateEcdsaPublicKey(key, authWrites, cert, certCustomization,
+                                    &ecdhCustomization);
+}
+
+error_code DS28C40::authenticateEcdsaPublicKey(
+    KeySecret key, bool authWrites, Ecc256::Signature::const_span cert,
+    span<const uint_least8_t> certCustomization,
+    const span<const uint_least8_t> * ecdhCustomization) {
+  const span<const uint_least8_t>::index_type minCustomizationSize = 1;
+  const span<const uint_least8_t>::index_type maxCertCustomizationSize = 32;
+  const span<const uint_least8_t>::index_type maxEcdhCustomizationSize = 48;
+  const span<const uint_least8_t>::index_type maxTotalCustomizationSize = 60;
+
+  if (!(certCustomization.size() >= minCustomizationSize &&
+        certCustomization.size() <= maxCertCustomizationSize &&
+        (!ecdhCustomization ||
+         (ecdhCustomization->size() >= minCustomizationSize &&
+          ecdhCustomization->size() <= maxEcdhCustomizationSize &&
+          certCustomization.size() + ecdhCustomization->size() <=
+              maxTotalCustomizationSize)))) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  if (key == KeySecretS) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t
+      request[2 + 2 * Ecc256::Scalar::size + maxTotalCustomizationSize];
+  uint_least8_t * requestIt = request;
+  *requestIt++ = 0xA8;
+  *requestIt++ = static_cast<uint_least8_t>(
+      ((certCustomization.size() - 1) << 3) | (key << 2) |
+      ((ecdhCustomization != NULL) << 1) | (authWrites << 0));
+  requestIt = copy(cert.r.begin(), cert.r.end(), requestIt);
+  requestIt = copy(cert.s.begin(), cert.s.end(), requestIt);
+  requestIt =
+      copy(certCustomization.begin(), certCustomization.end(), requestIt);
+  int delay = verifyEcdsaTimeMs;
+  if (ecdhCustomization) {
+    const span<const uint_least8_t>::index_type certCustomizationPaddingSize =
+        maxCertCustomizationSize - certCustomization.size();
+    std::fill_n(requestIt, certCustomizationPaddingSize, 0);
+    requestIt += certCustomizationPaddingSize;
+    requestIt =
+        copy(ecdhCustomization->begin(), ecdhCustomization->end(), requestIt);
+    delay += verifyEcdsaTimeMs;
+  }
+  return runCommand(make_span(request, requestIt), delay);
+}
+
+error_code DS28C40::authenticatedEcdsaWriteMemory(
+    int pageNum, bool useKeyS, Page::const_span newPageData,
+    Ecc256::Signature::const_span signature) {
+  return authenticatedEcdsaWriteMemory(pageNum, useKeyS, newPageData, signature,
+                                       NULL);
+}
+
+error_code DS28C40::authenticatedEcdsaWriteMemory(
+    int pageNum, bool useKeyS, Page::const_span newPageData,
+    Ecc256::Signature::const_span signature,
+    EncryptionChallenge::const_span challenge) {
+  return authenticatedEcdsaWriteMemory(pageNum, useKeyS, newPageData, signature,
+                                       &challenge);
+}
+
+error_code DS28C40::authenticatedEcdsaWriteMemory(
+    int pageNum, bool useKeyS, Page::const_span newPageData,
+    Ecc256::Signature::const_span signature,
+    const EncryptionChallenge::const_span * challenge) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t request[2 + Page::size + 2 * Ecc256::Scalar::size +
+                        EncryptionChallenge::size];
+  uint_least8_t * requestIt = request;
+  *requestIt++ = 0x89;
+  *requestIt = pageNum;
+  if (useKeyS) {
+    *requestIt |= 0x80;
+  }
+  requestIt = copy(newPageData.begin(), newPageData.end(), ++requestIt);
+  requestIt = copy(signature.r.begin(), signature.r.end(), requestIt);
+  requestIt = copy(signature.s.begin(), signature.s.end(), requestIt);
+  int delay = verifyEcdsaTimeMs + writeMemoryTimeMs;
+  if (challenge) {
+    requestIt = copy(challenge->begin(), challenge->end(), requestIt);
+    delay += computeTimeMs;
+  }
+  return runCommand(make_span(request, requestIt), delay);
+}
+
+error_code DS28C40::authenticatedSha256WriteMemory(int pageNum, bool useSecretS,
+                                                   Page::const_span newPageData,
+                                                   Page::const_span hmac) {
+  return authenticatedSha256WriteMemory(pageNum, useSecretS, newPageData, hmac,
+                                        NULL);
+}
+
+error_code DS28C40::authenticatedSha256WriteMemory(
+    int pageNum, bool useSecretS, Page::const_span newPageData,
+    Page::const_span hmac, EncryptionChallenge::const_span challenge) {
+  return authenticatedSha256WriteMemory(pageNum, useSecretS, newPageData, hmac,
+                                        &challenge);
+}
+
+error_code DS28C40::authenticatedSha256WriteMemory(
+    int pageNum, bool useSecretS, Page::const_span newPageData,
+    Page::const_span hmac, const EncryptionChallenge::const_span * challenge) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t request[3 + 2 * Page::size + EncryptionChallenge::size];
+  uint_least8_t * requestIt = request;
+  *requestIt++ = 0x99;
+  *requestIt++ = pageNum;
+  *requestIt++ = useSecretS ? 2 : 0;
+  requestIt = copy(newPageData.begin(), newPageData.end(), requestIt);
+  requestIt = copy(hmac.begin(), hmac.end(), requestIt);
+  int delay = writeMemoryTimeMs + computeTimeMs;
+  if (challenge) {
+    requestIt = copy(challenge->begin(), challenge->end(), requestIt);
+    delay += computeTimeMs;
+  }
+  return runCommand(make_span(request, requestIt), delay);
+}
+
+error_code
+DS28C40::computeAndWriteSha256Secret(int pageNum, KeySecret masterSecret,
+                                     KeySecret destinationSecret,
+                                     Page::const_span partialSecret) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t request[3 + Page::size];
+  request[0] = 0x3C;
+  request[1] = pageNum;
+  request[2] = (destinationSecret << 2) | masterSecret;
+  copy(partialSecret.begin(), partialSecret.end(), request + 3);
+  return runCommand(request, writeMemoryTimeMs + computeTimeMs);
+}
+
+error_code DS28C40::generateEcc256KeyPair(KeySecret key) {
+  if (key == KeySecretS) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const uint_least8_t request[] = {0xCB, key == KeySecretB};
+  return runCommand(request, generateEccKeyPairTimeMs);
+}
+
+error_code DS28C40::readRng(span<uint_least8_t> data) {
+  const span<uint_least8_t>::index_type maxDataSize = 64;
+  if ((data.size() < 1) || (data.size() > maxDataSize)) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[1 + maxDataSize];
+  buffer[0] = readRngCmd;
+  buffer[1] = static_cast<uint_least8_t>(data.size() - 1);
+  span<uint_least8_t> response(buffer, 1 + data.size());
+  const error_code result =
+      runCommand(make_span(buffer, 2), trngGenerationTimeMs, response);
+  if (!result) {
+    copy(response.begin(), response.end(), data.begin());
+  }
+  return result;
+}
+
+error_code DS28C40::entropyHealthTest() {
+  const uint_least8_t request[] = {readRngCmd, 0x80};
+  return runCommand(request, trngOnDemandCheckTimeMs);
+}
+
+error_code DS28C40::runCommand(span<const uint_least8_t> request, int delayTime,
+                               span<uint_least8_t> & response) {
+  const span<const uint_least8_t>::index_type responseInputSize =
+      response.size();
+  error_code result = doRunCommand(request, delayTime, response);
+  if (result) {
+    return result;
+  }
+  if (response.empty()) {
+    return make_error_code(InvalidResponseError);
+  }
+  // Parse command result byte.
+  switch (response[0]) {
+  case 0xAA:
+    // Success response.
+    if (response.size() != responseInputSize) {
+      result = make_error_code(InvalidResponseError);
+    }
+    break;
+
+  case 0x00:
+    result = make_error_code(AuthenticationError);
+    break;
+
+  default:
+    result.assign(response[0], errorCategory());
+    break;
+  }
+  response = response.subspan(1);
+  return result;
+}
+
+error_code DS28C40::runCommand(span<const uint_least8_t> request,
+                               int delayTime) {
+  uint_least8_t buffer;
+  span<uint_least8_t> response(&buffer, 1);
+  return runCommand(request, delayTime, response);
+}
+
+const error_category & DS28C40::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "DS28C40"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case InvalidOperationError:
+        return "Invalid Operation Error";
+
+      case InvalidParameterError:
+        return "Invalid Parameter Error";
+
+      case InvalidSequenceError:
+        return "Invalid Sequence Error";
+
+      case AuthenticationError:
+        return "Authentication Error";
+
+      case InternalError:
+        return "Internal Error";
+
+      case DeviceDisabledError:
+        return "Device Disabled Error";
+
+      case InvalidResponseError:
+        return "Invalid Response Error";
+      }
+      return defaultErrorMessage(condition);
+    }
+  } instance;
+  return instance;
+}
+
+error_code computeMultiblockHash(DS28C40 & device,
+                                 span<const uint_least8_t> data) {
+  error_code result;
+  span<const uint_least8_t>::index_type dataIdx = 0;
+  while (dataIdx < data.size() && !result) {
+    const span<const uint_least8_t>::index_type remainingSize =
+        data.size() - dataIdx;
+    const span<const uint_least8_t>::index_type chunkSize =
+        std::min<span<const uint_least8_t>::index_type>(remainingSize, 64);
+    result =
+        device.computeMultiblockHash(dataIdx == 0, remainingSize == chunkSize,
+                                     data.subspan(dataIdx, chunkSize));
+    dataIdx += chunkSize;
+  }
+  return result;
+}
+
+error_code readRomIdAndManId(DS28C40 & device, RomId::span romId,
+                             ManId::span manId) {
+  DS28C40::Page::array page;
+  error_code result = device.readMemory(DS28C40::romOptionsPage, page);
+  if (!result) {
+    const DS28C40::RomOptions romOptions(page);
+    copy(romOptions.romId(), romId);
+    copy(romOptions.manId(), manId);
+  }
+  return result;
+}
+
+static void setAnonymous(RomId::span romId) {
+  std::fill(romId.begin(), romId.end(), 0xFF);
+}
+
+DS28C40::PageAuthenticationData &
+DS28C40::PageAuthenticationData::setAnonymousRomId() {
+  setAnonymous(romId());
+  return *this;
+}
+
+DS28C40::ComputeSecretData::ComputeSecretData() : data() {
+  setPageNum(0);
+  setManId(ManId::array());
+}
+
+DS28C40::ComputeSecretData &
+DS28C40::ComputeSecretData::setManId(ManId::const_span manId) {
+  ManId::array validatedManId;
+  copy(manId, make_span(validatedManId));
+  validatedManId[1] |= 0x80;
+  data.setManId(validatedManId);
+  return *this;
+}
+
+DS28C40::DecryptionHmacData & DS28C40::DecryptionHmacData::setAnonymousRomId() {
+  setAnonymous(romId());
+  return *this;
+}
+
+} // namespace MaximInterfaceDevices
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS28C40.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,983 @@
+/*******************************************************************************
+* Copyright (C) 2019 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 MaximInterfaceDevices_DS28C40
+#define MaximInterfaceDevices_DS28C40
+
+#include <stdint.h>
+#include <MaximInterfaceCore/Algorithm.hpp>
+#include <MaximInterfaceCore/array_span.hpp>
+#include <MaximInterfaceCore/Ecc256.hpp>
+#include <MaximInterfaceCore/FlagSet.hpp>
+#include <MaximInterfaceCore/ManId.hpp>
+#include <MaximInterfaceCore/Optional.hpp>
+#include <MaximInterfaceCore/RomId.hpp>
+#include <MaximInterfaceCore/RunCommand.hpp>
+#include <MaximInterfaceCore/system_error.hpp>
+#include "Config.hpp"
+
+namespace MaximInterfaceDevices {
+
+class DS28C40 {
+public:
+  /// Device command results.
+  enum ErrorValue {
+    InternalError = 0x22,
+    InvalidSequenceError = 0x33,
+    InvalidOperationError = 0x55,
+    InvalidParameterError = 0x77,
+    DeviceDisabledError = 0x88,
+    AuthenticationError = 0x100,
+    InvalidResponseError ///< Command response does not match expected format.
+  };
+
+  /// @name Device memory pages
+  /// @{
+
+  static const int publicKeyAxPage = 28;
+  static const int publicKeyAyPage = 29;
+  static const int publicKeyBxPage = 30;
+  static const int publicKeyByPage = 31;
+  static const int authorityPublicKeyAxPage = 32;
+  static const int authorityPublicKeyAyPage = 33;
+  static const int authorityPublicKeyBxPage = 34;
+  static const int authorityPublicKeyByPage = 35;
+  static const int privateKeyAPage = 36;
+  static const int privateKeyBPage = 37;
+  static const int secretAPage = 38;
+  static const int secretBPage = 39;
+  static const int romOptionsPage = 40;
+  static const int gpioControlPage = 41;
+  static const int publicKeySxPage = 42;
+  static const int publicKeySyPage = 43;
+
+  /// @}
+
+  static const int memoryPages = 44;
+  static const int protectionBlocks = 9;
+
+  /// Key or secret to use for operation.
+  enum KeySecret { KeySecretA = 0, KeySecretB = 1, KeySecretS = 2 };
+
+  /// Available PIO states when verifying an ECDSA signature.
+  enum GpioState { Unchanged, Conducting, HighImpedance };
+
+  /// Holds a device memory page.
+  typedef Core::array_span<uint_least8_t, 32> Page;
+
+  /// Challenge for an encrypted device memory page.
+  typedef Core::array_span<uint_least8_t, 8> EncryptionChallenge;
+
+  // Format page authentication input data.
+  class PageAuthenticationData;
+
+  // Format authenticated write input data.
+  class WriteAuthenticationData;
+
+  // Format compute secret input data.
+  class ComputeSecretData;
+
+  // Format decryption HMAC input data.
+  class DecryptionHmacData;
+
+  // Format encryption HMAC input data.
+  class EncryptionHmacData;
+
+  // Access fields in the ROM Options page.
+  class RomOptions;
+
+  // Access fields in the GPIO Control page.
+  class GpioControl;
+
+  /// Page protection types.
+  enum BlockProtectionType {
+    RP = 0x01,  ///< Read protection.
+    WP = 0x02,  ///< Write protection.
+    EM = 0x04,  ///< EPROM emulation mode.
+    APH = 0x08, ///< Authentication Write Protection HMAC
+    EPH = 0x10, ///< Encryption and Authentication Write Protection HMAC
+    ECH = 0x40, ///< Encryption and write using shared key from ECDH
+    ECW = 0x80  ///< Authentication Write Protection ECDSA
+  };
+  typedef Core::FlagSet<BlockProtectionType, 8> BlockProtection;
+
+  explicit DS28C40(const Core::RunCommand & runCommand)
+      : doRunCommand(runCommand) {}
+
+  void setRunCommand(const Core::RunCommand & runCommand) {
+    doRunCommand = runCommand;
+  }
+
+  /// @brief Write memory with no protection.
+  /// @param pageNum Number of page to write.
+  /// @param page Data to write.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeMemory(int pageNum, Page::const_span page);
+
+  /// @brief Read memory with no protection.
+  /// @param pageNum Number of page to read.
+  /// @param[out] page Data that was read.
+  MaximInterfaceDevices_EXPORT Core::error_code readMemory(int pageNum,
+                                                           Page::span page);
+
+  /// @brief Read memory with encryption.
+  /// @param pageNum Number of page to read from.
+  /// @param secret Secret to use for encryption.
+  /// @param[out] challenge Encryption challenge that was read.
+  /// @param[out] encryptedPage Encrypted page data that was read.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  encryptedReadMemory(int pageNum, KeySecret secret,
+                      EncryptionChallenge::span challenge,
+                      Page::span encryptedPage);
+
+  /// @brief Read the protection settings of a block.
+  /// @param blockNum Number of block to read.
+  /// @param[out] keySecret Secret key set on the block or empty if not set.
+  /// @param[out] protection Protection that was read.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readBlockProtection(int blockNum, Core::Optional<KeySecret> & keySecret,
+                      BlockProtection & protection);
+
+  /// @brief Set the protection settings of a block.
+  /// @param blockNum Number of block to write.
+  /// @param keySecret Secret/Key A or B.
+  /// @param protection Protection to write.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  setBlockProtection(int blockNum, KeySecret keySecret,
+                     const BlockProtection & protection);
+
+  /// @brief Compute and read page authentication with ECDSA.
+  /// @param pageNum Number of page to authenticate.
+  /// @param key
+  /// Private key to use for authentication.
+  /// Key S cannot be used with this command.
+  /// @param challenge Random challenge used to prevent replay attacks.
+  /// @param[out] signature Computed page signature.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeAndReadPageAuthentication(int pageNum, KeySecret key,
+                                   Page::const_span challenge,
+                                   Core::Ecc256::Signature::span signature);
+
+  /// @brief Compute and read page authentication with HMAC.
+  /// @param pageNum Number of page to authenticate.
+  /// @param secret
+  /// Secret to use for authentication.
+  /// Secret S cannot be used with this command.
+  /// @param challenge Random challenge used to prevent replay attacks.
+  /// @param[out] hmac Computed page HMAC.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeAndReadPageAuthentication(int pageNum, KeySecret secret,
+                                   Page::const_span challenge, Page::span hmac);
+
+  /// @brief 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. Should be 64 bytes unless this is the last block.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeMultiblockHash(bool firstBlock, bool lastBlock,
+                        Core::span<const uint_least8_t> data);
+
+  /// @brief Verify ECDSA signature with data input.
+  /// @param key Public key to use for verification.
+  /// @param authorityKey Use the authority key instead of the standard key.
+  /// @param gpioState New state of the GPIO pin if verification successful.
+  /// @param signature Signature to verify.
+  /// @param data Data to verify with length from 1 to 64.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState,
+                       Core::Ecc256::Signature::const_span signature,
+                       Core::span<const uint_least8_t> data);
+
+  /// @brief Verify ECDSA signature with hash input.
+  /// @param key Public key to use for verification.
+  /// @param authorityKey Use the authority key instead of the standard key.
+  /// @param gpioState New state of the GPIO pin if verification successful.
+  /// @param signature Signature to verify.
+  /// @param hash Hash of data to verify.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState,
+                       Core::Ecc256::Signature::const_span signature,
+                       Page::const_span hash);
+
+  /// @brief
+  /// Verify ECDSA signature with THASH input from Compute Multiblock Hash.
+  /// @param key Public key to use for verification.
+  /// @param authorityKey Use the authority key instead of the standard key.
+  /// @param gpioState New state of the GPIO pin if verification successful.
+  /// @param signature Signature to verify.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState,
+                       Core::Ecc256::Signature::const_span signature);
+
+  /// @brief Authenticate a public key for authenticated writes.
+  /// @param key
+  /// Authority key to use for authentication. Key A or B can be selected.
+  /// @param cert Certificate to use for authentication of Public Key S.
+  /// @param certCustomization
+  /// Certificate customization with length from 1 to 32.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  authenticateEcdsaPublicKey(KeySecret key,
+                             Core::Ecc256::Signature::const_span cert,
+                             Core::span<const uint_least8_t> certCustomization);
+
+  /// @brief
+  /// Authenticate a public key for ECDH and optionally authenticated writes.
+  /// @param key
+  /// Keys to use for authentication and ECDH key exchange.
+  /// Key A or B can be selected.
+  /// @param authWrites True to select authentication for writes.
+  /// @param cert Certificate to use for authentication of Public Key S.
+  /// @param certCustomization
+  /// Certificate customization with length from 1 to 32.
+  /// @param ecdhCustomization ECDH customization with length from 1 to 48.
+  /// @note The maximum total customization length is 60 bytes.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  authenticateEcdsaPublicKey(KeySecret key, bool authWrites,
+                             Core::Ecc256::Signature::const_span cert,
+                             Core::span<const uint_least8_t> certCustomization,
+                             Core::span<const uint_least8_t> ecdhCustomization);
+
+  /// @brief Write with ECDSA authentication.
+  /// @param pageNum Number of page to write.
+  /// @param useKeyS
+  /// Use Public Key S instead of the authority key set in the block protection.
+  /// @param newPageData Data to write.
+  /// @param signature Signature to use for authentication of page data.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  authenticatedEcdsaWriteMemory(int pageNum, bool useKeyS,
+                                Page::const_span newPageData,
+                                Core::Ecc256::Signature::const_span signature);
+
+  /// @brief Write with ECDSA authentication and encryption.
+  /// @param pageNum Number of page to write.
+  /// @param useKeyS
+  /// Use Public Key S instead of the authority key set in the block protection.
+  /// @param newPageData Encrypted data to write.
+  /// @param signature Signature to use for authentication of page data.
+  /// @param challenge Challenge to use for decryption of page data.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  authenticatedEcdsaWriteMemory(int pageNum, bool useKeyS,
+                                Page::const_span newPageData,
+                                Core::Ecc256::Signature::const_span signature,
+                                EncryptionChallenge::const_span challenge);
+
+  /// @brief Write with SHA-256 HMAC authentication.
+  /// @param pageNum Number of page to write.
+  /// @param useSecretS
+  /// Use Secret S instead of the secret set in the block protection.
+  /// @param newPageData Data to write.
+  /// @param hmac HMAC to use for authentication of page data.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  authenticatedSha256WriteMemory(int pageNum, bool useSecretS,
+                                 Page::const_span newPageData,
+                                 Page::const_span hmac);
+
+  /// @brief Write with SHA-256 HMAC authentication and encryption.
+  /// @param pageNum Number of page to write.
+  /// @param useSecretS
+  /// Use Secret S instead of the secret set in the block protection.
+  /// @param newPageData Data to write.
+  /// @param hmac HMAC to use for authentication of page data.
+  /// @param challenge Challenge to use for decryption of page data.
+  MaximInterfaceDevices_EXPORT Core::error_code authenticatedSha256WriteMemory(
+      int pageNum, bool useSecretS, Page::const_span newPageData,
+      Page::const_span hmac, EncryptionChallenge::const_span challenge);
+
+  /// @brief Compute a derivative SHA-256 secret from an existing secret.
+  /// @param pageNum Number of page to use in computation.
+  /// @param masterSecret Master secret to use in computation.
+  /// @param destinationSecret
+  /// Destination secret to receive the computation result.
+  /// @param partialSecret Partial secret to use in computation.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeAndWriteSha256Secret(int pageNum, KeySecret masterSecret,
+                              KeySecret destinationSecret,
+                              Page::const_span partialSecret);
+
+  /// @brief Generate a new ECDSA key pair.
+  /// @param key Key to generate. Key S cannot be used with this command.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  generateEcc256KeyPair(KeySecret key);
+
+  /// @brief Read a block of random data from the RNG.
+  /// @param[out] data Random data from RNG with length from 1 to 64.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readRng(Core::span<uint_least8_t> data);
+
+  /// Run entropy health test on the RNG.
+  MaximInterfaceDevices_EXPORT Core::error_code entropyHealthTest();
+
+  MaximInterfaceDevices_EXPORT static const Core::error_category &
+  errorCategory();
+
+private:
+  enum HashType { HashInput, DataInput, THASH };
+
+  Core::error_code
+  verifyEcdsaSignature(KeySecret key, bool authorityKey, HashType hashType,
+                       GpioState gpioState,
+                       Core::Ecc256::Signature::const_span signature,
+                       Core::span<const uint_least8_t> buffer);
+
+  Core::error_code authenticateEcdsaPublicKey(
+      KeySecret key, bool authWrites, Core::Ecc256::Signature::const_span cert,
+      Core::span<const uint_least8_t> certCustomization,
+      const Core::span<const uint_least8_t> * ecdhCustomization);
+
+  Core::error_code authenticatedEcdsaWriteMemory(
+      int pageNum, bool useKeyS, Page::const_span newPageData,
+      Core::Ecc256::Signature::const_span signature,
+      const EncryptionChallenge::const_span * challenge);
+
+  Core::error_code authenticatedSha256WriteMemory(
+      int pageNum, bool useSecretS, Page::const_span newPageData,
+      Page::const_span hmac, const EncryptionChallenge::const_span * challenge);
+
+  Core::error_code runCommand(Core::span<const uint_least8_t> request,
+                              int delayTime,
+                              Core::span<uint_least8_t> & response);
+
+  Core::error_code runCommand(Core::span<const uint_least8_t> request,
+                              int delayTime);
+
+  Core::RunCommand doRunCommand;
+};
+
+inline Core::error_code make_error_code(DS28C40::ErrorValue e) {
+  return Core::error_code(e, DS28C40::errorCategory());
+}
+
+/// @brief
+/// Hash arbitrary length data with successive Compute Multiblock Hash commands.
+/// @param device Device for computation.
+/// @param data Data to hash.
+MaximInterfaceDevices_EXPORT Core::error_code
+computeMultiblockHash(DS28C40 & device, Core::span<const uint_least8_t> data);
+
+/// @brief
+/// Read the device ROM ID and MAN ID using the Read Memory command on the
+/// ROM Options page.
+/// @param device Device to read.
+/// @param[out] romId Read ROM ID valid when operation is successful.
+/// @param[out] manId Read MAN ID valid when operation is successful.
+MaximInterfaceDevices_EXPORT Core::error_code
+readRomIdAndManId(DS28C40 & device, Core::RomId::span romId,
+                  Core::ManId::span manId);
+
+/// Format page authentication input data.
+class DS28C40::PageAuthenticationData {
+public:
+  typedef Core::array_span<uint_least8_t, Core::RomId::size + 2 * Page::size +
+                                              1 + Core::ManId::size>
+      Result;
+
+  PageAuthenticationData() : result_() {}
+
+  /// Formatted data result.
+  Result::const_span result() const { return result_; }
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() {
+    return make_span(result_).subspan<romIdIdx, Core::RomId::size>();
+  }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const {
+    return const_cast<PageAuthenticationData &>(*this).romId();
+  }
+
+  /// Set ROM ID.
+  PageAuthenticationData & setRomId(Core::RomId::const_span romId) {
+    copy(romId, this->romId());
+    return *this;
+  }
+
+  /// Set ROM ID for use in anonymous mode.
+  MaximInterfaceDevices_EXPORT PageAuthenticationData & setAnonymousRomId();
+
+  /// @}
+
+  /// @name Page
+  /// @brief Data from a device memory page.
+  /// @{
+
+  /// Get mutable page.
+  Page::span page() {
+    return make_span(result_).subspan<pageIdx, Page::size>();
+  }
+
+  /// Get immutable page.
+  Page::const_span page() const {
+    return const_cast<PageAuthenticationData &>(*this).page();
+  }
+
+  /// Set page.
+  PageAuthenticationData & setPage(Page::const_span page) {
+    copy(page, this->page());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Challenge
+  /// @brief Random challenge used to prevent replay attacks.
+  /// @{
+
+  /// Get mutable Challenge.
+  Page::span challenge() {
+    return make_span(result_).subspan<challengeIdx, Page::size>();
+  }
+
+  /// Get immutable Challenge.
+  Page::const_span challenge() const {
+    return const_cast<PageAuthenticationData &>(*this).challenge();
+  }
+
+  /// Set Challenge.
+  PageAuthenticationData & setChallenge(Page::const_span challenge) {
+    copy(challenge, this->challenge());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Number of the page to use data from.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return result_[pageNumIdx]; }
+
+  /// Set page number.
+  PageAuthenticationData & setPageNum(int pageNum) {
+    result_[pageNumIdx] = pageNum;
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() {
+    return make_span(result_).subspan<manIdIdx, Core::ManId::size>();
+  }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const {
+    return const_cast<PageAuthenticationData &>(*this).manId();
+  }
+
+  /// Set MAN ID.
+  PageAuthenticationData & setManId(Core::ManId::const_span manId) {
+    copy(manId, this->manId());
+    return *this;
+  }
+
+  /// @}
+
+private:
+  typedef Result::span::index_type index;
+
+  static const index romIdIdx = 0;
+  static const index pageIdx = romIdIdx + Core::RomId::size;
+  static const index challengeIdx = pageIdx + Page::size;
+  static const index pageNumIdx = challengeIdx + Page::size;
+  static const index manIdIdx = pageNumIdx + 1;
+
+  Result::array result_;
+};
+
+/// Format authenticated write input data.
+class DS28C40::WriteAuthenticationData {
+public:
+  typedef PageAuthenticationData::Result Result;
+
+  WriteAuthenticationData() : data() { setPageNum(0); }
+
+  /// Formatted data result.
+  Result::const_span result() const { return data.result(); }
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() { return data.romId(); }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const { return data.romId(); }
+
+  /// Set ROM ID.
+  WriteAuthenticationData & setRomId(Core::RomId::const_span romId) {
+    data.setRomId(romId);
+    return *this;
+  }
+
+  /// Set ROM ID for use in anonymous mode.
+  WriteAuthenticationData & setAnonymousRomId() {
+    data.setAnonymousRomId();
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Old page
+  /// @brief Existing data contained in the page.
+  /// @{
+
+  /// Get mutable old page.
+  Page::span oldPage() { return data.page(); }
+
+  /// Get immutable old page.
+  Page::const_span oldPage() const { return data.page(); }
+
+  /// Set old page.
+  WriteAuthenticationData & setOldPage(Page::const_span oldPage) {
+    data.setPage(oldPage);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name New page
+  /// @brief New data to write to the page.
+  /// @{
+
+  /// Get mutable new page.
+  Page::span newPage() { return data.challenge(); }
+
+  /// Get immutable new page.
+  Page::const_span newPage() const { return data.challenge(); }
+
+  /// Set new page.
+  WriteAuthenticationData & setNewPage(Page::const_span newPage) {
+    data.setChallenge(newPage);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Page number for write operation.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return data.pageNum() & 0x7F; }
+
+  /// Set page number.
+  WriteAuthenticationData & setPageNum(int pageNum) {
+    data.setPageNum(pageNum | 0x80);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() { return data.manId(); }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const { return data.manId(); }
+
+  /// Set MAN ID.
+  WriteAuthenticationData & setManId(Core::ManId::const_span manId) {
+    data.setManId(manId);
+    return *this;
+  }
+
+  /// @}
+
+private:
+  PageAuthenticationData data;
+};
+
+/// Format compute secret input data.
+class DS28C40::ComputeSecretData {
+public:
+  typedef PageAuthenticationData::Result Result;
+
+  MaximInterfaceDevices_EXPORT ComputeSecretData();
+
+  /// Formatted data result.
+  Result::const_span result() const { return data.result(); }
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() { return data.romId(); }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const { return data.romId(); }
+
+  /// Set ROM ID.
+  ComputeSecretData & setRomId(Core::RomId::const_span romId) {
+    data.setRomId(romId);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Binding Data
+  /// @brief Binding Data contained in the selected page.
+  /// @{
+
+  /// Get mutable Binding Data.
+  Page::span bindingData() { return data.page(); }
+
+  /// Get immutable Binding Data.
+  Page::const_span bindingData() const { return data.page(); }
+
+  /// Set Binding Data.
+  ComputeSecretData & setBindingData(Page::const_span bindingData) {
+    data.setPage(bindingData);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Partial Secret
+  /// @brief Partial Secret used for customization.
+  /// @{
+
+  /// Get mutable Partial Secret.
+  Page::span partialSecret() { return data.challenge(); }
+
+  /// Get immutable Partial Secret.
+  Page::const_span partialSecret() const { return data.challenge(); }
+
+  /// Set Partial Secret.
+  ComputeSecretData & setPartialSecret(Page::const_span partialSecret) {
+    data.setChallenge(partialSecret);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Page number for Binding Data.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return data.pageNum() & 0x3F; }
+
+  /// Set page number.
+  ComputeSecretData & setPageNum(int pageNum) {
+    data.setPageNum(pageNum | 0xC0);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const { return data.manId(); }
+
+  /// Set MAN ID.
+  MaximInterfaceDevices_EXPORT ComputeSecretData &
+  setManId(Core::ManId::const_span manId);
+
+  /// @}
+
+private:
+  PageAuthenticationData data;
+};
+
+/// Format decryption HMAC input data.
+class DS28C40::DecryptionHmacData {
+public:
+  typedef Core::array_span<uint_least8_t, EncryptionChallenge::size +
+                                              Core::RomId::size + 1 +
+                                              Core::ManId::size>
+      Result;
+
+  DecryptionHmacData() : result_() {}
+
+  /// Formatted data result.
+  Result::const_span result() const { return result_; }
+
+  /// @name Encryption Challenge
+  /// @brief Random challenge used to prevent replay attacks.
+  /// @{
+
+  /// Get mutable Encryption Challenge.
+  EncryptionChallenge::span encryptionChallenge() {
+    return make_span(result_)
+        .subspan<encryptionChallengeIdx, EncryptionChallenge::size>();
+  }
+
+  /// Get immutable Encryption Challenge.
+  EncryptionChallenge::const_span encryptionChallenge() const {
+    return const_cast<DecryptionHmacData &>(*this).encryptionChallenge();
+  }
+
+  /// Set Encryption Challenge.
+  DecryptionHmacData &
+  setEncryptionChallenge(EncryptionChallenge::const_span encryptionChallenge) {
+    copy(encryptionChallenge, this->encryptionChallenge());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() {
+    return make_span(result_).subspan<romIdIdx, Core::RomId::size>();
+  }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const {
+    return const_cast<DecryptionHmacData &>(*this).romId();
+  }
+
+  /// Set ROM ID.
+  DecryptionHmacData & setRomId(Core::RomId::const_span romId) {
+    copy(romId, this->romId());
+    return *this;
+  }
+
+  /// Set ROM ID for use in anonymous mode.
+  MaximInterfaceDevices_EXPORT DecryptionHmacData & setAnonymousRomId();
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Number of the page to use data from.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return result_[pageNumIdx]; }
+
+  /// Set page number.
+  DecryptionHmacData & setPageNum(int pageNum) {
+    result_[pageNumIdx] = pageNum;
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() {
+    return make_span(result_).subspan<manIdIdx, Core::ManId::size>();
+  }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const {
+    return const_cast<DecryptionHmacData &>(*this).manId();
+  }
+
+  /// Set MAN ID.
+  DecryptionHmacData & setManId(Core::ManId::const_span manId) {
+    copy(manId, this->manId());
+    return *this;
+  }
+
+  /// @}
+
+private:
+  typedef Result::span::index_type index;
+
+  static const index encryptionChallengeIdx = 0;
+  static const index romIdIdx =
+      encryptionChallengeIdx + EncryptionChallenge::size;
+  static const index pageNumIdx = romIdIdx + Core::RomId::size;
+  static const index manIdIdx = pageNumIdx + 1;
+
+  Result::array result_;
+};
+
+/// Format encryption HMAC input data.
+class DS28C40::EncryptionHmacData {
+public:
+  typedef DecryptionHmacData::Result Result;
+
+  EncryptionHmacData() : data() { setPageNum(0); }
+
+  /// Formatted data result.
+  Result::const_span result() const { return data.result(); }
+
+  /// @name Encryption Challenge
+  /// @brief Random challenge used to prevent replay attacks.
+  /// @{
+
+  /// Get mutable Encryption Challenge.
+  EncryptionChallenge::span encryptionChallenge() {
+    return data.encryptionChallenge();
+  }
+
+  /// Get immutable Encryption Challenge.
+  EncryptionChallenge::const_span encryptionChallenge() const {
+    return data.encryptionChallenge();
+  }
+
+  /// Set Encryption Challenge.
+  EncryptionHmacData &
+  setEncryptionChallenge(EncryptionChallenge::const_span encryptionChallenge) {
+    data.setEncryptionChallenge(encryptionChallenge);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() { return data.romId(); }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const { return data.romId(); }
+
+  /// Set ROM ID.
+  EncryptionHmacData & setRomId(Core::RomId::const_span romId) {
+    data.setRomId(romId);
+    return *this;
+  }
+
+  /// Set ROM ID for use in anonymous mode.
+  EncryptionHmacData & setAnonymousRomId() {
+    data.setAnonymousRomId();
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Number of the page to use data from.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return data.pageNum() & 0x7F; }
+
+  /// Set page number.
+  EncryptionHmacData & setPageNum(int pageNum) {
+    data.setPageNum(pageNum | 0x80);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() { return data.manId(); }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const { return data.manId(); }
+
+  /// Set MAN ID.
+  EncryptionHmacData & setManId(Core::ManId::const_span manId) {
+    data.setManId(manId);
+    return *this;
+  }
+
+  /// @}
+
+private:
+  DecryptionHmacData data;
+};
+
+/// Access fields in the ROM Options page.
+class DS28C40::RomOptions {
+public:
+  explicit RomOptions(Page::span page) : page(page) {}
+
+  bool anonymous() const { return page[anonymousIdx] == anonymousValue; }
+
+  void setAnonymous(bool anonymous) {
+    page[anonymousIdx] = (anonymous ? anonymousValue : 0);
+  }
+
+  Core::ManId::const_span manId() const {
+    return page.subspan<22, Core::ManId::size>();
+  }
+
+  Core::RomId::const_span romId() const {
+    return page.subspan<24, Core::RomId::size>();
+  }
+
+private:
+  static const Page::span::index_type anonymousIdx = 1;
+  static const Page::span::value_type anonymousValue = 0xAA;
+
+  Page::span page;
+};
+
+/// Access fields in the GPIO Control page.
+class DS28C40::GpioControl {
+public:
+  explicit GpioControl(Page::span page) : page(page) {}
+
+  bool conducting() const { return page[conductingIdx] == conductingValue; }
+
+  void setConducting(bool conducting) {
+    page[conductingIdx] = (conducting ? conductingValue : 0x55);
+  }
+
+  bool level() const { return page[2] == 0x55; }
+
+private:
+  static const Page::span::index_type conductingIdx = 0;
+  static const Page::span::value_type conductingValue = 0xAA;
+
+  Page::span page;
+};
+
+} // namespace MaximInterfaceDevices
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS28E15_22_25.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,653 @@
+/*******************************************************************************
+* 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 <MaximInterfaceCore/crc.hpp>
+#include <MaximInterfaceCore/Error.hpp>
+#include "DS28E15_22_25.hpp"
+
+namespace MaximInterfaceDevices {
+
+using namespace Core;
+using std::copy;
+
+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, span<const uint_least8_t> data,
+                 OneWireMaster::Level level = OneWireMaster::NormalLevel,
+                 uint_fast16_t crcStart = 0) {
+  error_code result = master.writeBlock(data);
+  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(calculateCrc16(crcStart, data), response) != 0xB001) {
+    result = make_error_code(DS28E15_22_25::CrcError);
+  }
+  return result;
+}
+
+const int DS28E15_22_25::segmentsPerPage;
+
+DS28E15_22_25::AuthenticationData &
+DS28E15_22_25::AuthenticationData::setAnonymousRomId() {
+  std::fill(romId().begin(), romId().end(), 0xFF);
+  return *this;
+}
+
+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, level);
+  }
+  return result;
+}
+
+static error_code readDataWithCrc(OneWireMaster & master,
+                                  span<uint_least8_t> data) {
+  error_code result = master.readBlock(data);
+  if (result) {
+    return result;
+  }
+  uint_least8_t response[2];
+  result = master.readBlock(response);
+  if (result) {
+    return result;
+  }
+  if (calculateCrc16(calculateCrc16(data), response) != 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, 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 &
+DS28E15_22_25::BlockProtection::setBlockNum(int blockNum) {
+  status &= ~blockNumMask;
+  status |= (blockNum & blockNumMask);
+  return *this;
+}
+
+bool DS28E15_22_25::BlockProtection::noProtection() const {
+  return !readProtection() && !writeProtection() && !eepromEmulation() &&
+         !authProtection();
+}
+
+DS28E15_22_25::BlockProtection &
+DS28E15_22_25::BlockProtection::setReadProtection(bool readProtection) {
+  if (readProtection) {
+    status |= readProtectionMask;
+  } else {
+    status &= ~readProtectionMask;
+  }
+  return *this;
+}
+
+DS28E15_22_25::BlockProtection &
+DS28E15_22_25::BlockProtection::setWriteProtection(bool writeProtection) {
+  if (writeProtection) {
+    status |= writeProtectionMask;
+  } else {
+    status &= ~writeProtectionMask;
+  }
+  return *this;
+}
+
+DS28E15_22_25::BlockProtection &
+DS28E15_22_25::BlockProtection::setEepromEmulation(bool eepromEmulation) {
+  if (eepromEmulation) {
+    status |= eepromEmulationMask;
+  } else {
+    status &= ~eepromEmulationMask;
+  }
+  return *this;
+}
+
+DS28E15_22_25::BlockProtection &
+DS28E15_22_25::BlockProtection::setAuthProtection(bool authProtection) {
+  if (authProtection) {
+    status |= authProtectionMask;
+  } else {
+    status &= ~authProtectionMask;
+  }
+  return *this;
+}
+
+DS28E15_22_25::ProtectionWriteMacData::ProtectionWriteMacData()
+    : result_(), oldProtection_(), newProtection_() {
+  setOldProtection(oldProtection_);
+  setNewProtection(newProtection_);
+}
+
+DS28E15_22_25::ProtectionWriteMacData &
+DS28E15_22_25::ProtectionWriteMacData::setOldProtection(
+    BlockProtection oldProtection) {
+  result_[oldProtectionIdx] = oldProtection.authProtection() ? 1 : 0;
+  result_[oldProtectionIdx + 1] = oldProtection.eepromEmulation() ? 1 : 0;
+  result_[oldProtectionIdx + 2] = oldProtection.writeProtection() ? 1 : 0;
+  result_[oldProtectionIdx + 3] = oldProtection.readProtection() ? 1 : 0;
+  oldProtection_ = oldProtection;
+  return *this;
+}
+
+DS28E15_22_25::ProtectionWriteMacData &
+DS28E15_22_25::ProtectionWriteMacData::setNewProtection(
+    BlockProtection newProtection) {
+  result_[blockNumIdx] = newProtection.blockNum();
+  result_[newProtectionIdx] = newProtection.authProtection() ? 1 : 0;
+  result_[newProtectionIdx + 1] = newProtection.eepromEmulation() ? 1 : 0;
+  result_[newProtectionIdx + 2] = newProtection.writeProtection() ? 1 : 0;
+  result_[newProtectionIdx + 3] = newProtection.readProtection() ? 1 : 0;
+  newProtection_ = newProtection;
+  return *this;
+}
+
+error_code
+DS28E15_22_25::writeAuthBlockProtection(BlockProtection newProtection,
+                                        Page::const_span mac) {
+  error_code result =
+      writeCommandWithCrc(AuthWriteBlockProtection, newProtection.statusByte(),
+                          OneWireMaster::StrongLevel);
+  if (result) {
+    return result;
+  }
+
+  sleep->invoke(shaComputationDelayMs);
+  result = master->setLevel(OneWireMaster::NormalLevel);
+  if (result) {
+    return result;
+  }
+
+  result = writeDataWithCrc(*master, mac);
+  if (result) {
+    return result;
+  }
+
+  result = readCsByte(*master);
+  if (result) {
+    return result;
+  }
+
+  result = releaseSequence(*master, *sleep, eepromWriteDelayMs);
+  return result;
+}
+
+error_code DS28E15_22_25::writeBlockProtection(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;
+}
+
+error_code DS28E15_22_25::computeReadPageMac(int page_num, bool anon,
+                                             Page::span mac) const {
+  error_code result =
+      writeCommandWithCrc(ComputePageMac, (anon ? 0xE0 : 0x00) | page_num,
+                          OneWireMaster::StrongLevel);
+  if (result) {
+    return result;
+  }
+
+  sleep->invoke(shaComputationDelayMs * 2);
+  result = master->setLevel(OneWireMaster::NormalLevel);
+  if (result) {
+    return result;
+  }
+
+  result = readCsByte(*master);
+  if (result) {
+    return result;
+  }
+
+  result = readDataWithCrc(*master, mac);
+  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(Page::const_span 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);
+  return result;
+}
+
+error_code DS28E15_22_25::doReadScratchpad(Page::span 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);
+  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::span rdbuf) const {
+  error_code result = writeCommandWithCrc(ReadMemory, page);
+  if (result) {
+    return result;
+  }
+
+  result = continueReadPage(rdbuf);
+  return result;
+}
+
+error_code DS28E15_22_25::continueReadPage(Page::span rdbuf) const {
+  return readDataWithCrc(*master, rdbuf);
+}
+
+error_code DS28E15_22_25::doWriteAuthSegment(Segment::const_span newData,
+                                             Page::const_span 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, OneWireMaster::StrongLevel, crcStart);
+  if (result) {
+    return result;
+  }
+
+  sleep->invoke(shaComputationDelayMs);
+  result = master->setLevel(OneWireMaster::NormalLevel);
+  if (result) {
+    return result;
+  }
+
+  result = writeDataWithCrc(*master, mac);
+  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,
+                                             Segment::const_span newData,
+                                             Page::const_span 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(
+    Segment::const_span newData, Page::const_span mac, Variant variant) {
+  return doWriteAuthSegment(newData, mac, variant, true);
+}
+
+error_code DS28E15_22_25::readSegment(int page, int segment,
+                                      Segment::span 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::span data) const {
+  return master->readBlock(data);
+}
+
+error_code DS28E15_22_25::writeSegment(int page, int block,
+                                       Segment::const_span data) {
+  error_code result = writeCommandWithCrc(WriteMemory, (block << 5) | page);
+  if (result) {
+    return result;
+  }
+
+  result = continueWriteSegment(data);
+  return result;
+}
+
+error_code DS28E15_22_25::continueWriteSegment(Segment::const_span data) {
+  error_code result = writeDataWithCrc(*master, data);
+  if (result) {
+    return result;
+  }
+
+  result = releaseSequence(*master, *sleep, eepromWriteDelayMs);
+  return result;
+}
+
+error_code
+DS28E15_22_25::doReadAllBlockProtection(span<BlockProtection> protection,
+                                        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);
+      if (!result) {
+        const int blocks = ((variant == DS28E22) ? DS28E22::memoryPages
+                                                 : DS28E25::memoryPages) /
+                           ds28e22_25_pagesPerBlock;
+        for (span<BlockProtection>::index_type i = 0;
+             i < std::min<span<BlockProtection>::index_type>(protection.size(),
+                                                             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);
+      if (!result) {
+        for (span<BlockProtection>::index_type i = 0;
+             i < std::min<span<BlockProtection>::index_type>(
+                     protection.size(), 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) {
+    uint_least8_t data[4];
+    result = readDataWithCrc(*master, data);
+    if (!result) {
+      personality.PB1 = data[0];
+      personality.PB2 = data[1];
+      personality.manId[0] = data[2];
+      personality.manId[1] = data[3];
+    }
+  }
+  return result;
+}
+
+const int DS28EL15::memoryPages;
+const int DS28EL15::protectionBlocks;
+
+error_code DS28EL15::writeScratchpad(Page::const_span data) {
+  return doWriteScratchpad(data, DS28E15);
+}
+
+error_code DS28EL15::readScratchpad(Page::span 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,
+                                      Segment::const_span newData,
+                                      Page::const_span mac) {
+  return doWriteAuthSegment(pageNum, segmentNum, newData, mac, DS28E15);
+}
+
+error_code DS28EL15::continueWriteAuthSegment(Segment::const_span newData,
+                                              Page::const_span mac) {
+  return doContinueWriteAuthSegment(newData, mac, DS28E15);
+}
+
+error_code DS28EL15::readAllBlockProtection(
+    span<BlockProtection, protectionBlocks> protection) const {
+  return doReadAllBlockProtection(protection, DS28E15);
+}
+
+error_code DS28E15::loadSecret(bool lock) { return doLoadSecret(lock, false); }
+
+error_code DS28E15::computeSecret(int pageNum, bool lock) {
+  return doComputeSecret(pageNum, lock, false);
+}
+
+const int DS28EL22::memoryPages;
+const int DS28EL22::protectionBlocks;
+
+error_code DS28EL22::writeScratchpad(Page::const_span data) {
+  return doWriteScratchpad(data, DS28E22);
+}
+
+error_code DS28EL22::readScratchpad(Page::span 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,
+                                      Segment::const_span newData,
+                                      Page::const_span mac) {
+  return doWriteAuthSegment(pageNum, segmentNum, newData, mac, DS28E22);
+}
+
+error_code DS28EL22::continueWriteAuthSegment(Segment::const_span newData,
+                                              Page::const_span mac) {
+  return doContinueWriteAuthSegment(newData, mac, DS28E22);
+}
+
+error_code DS28EL22::readAllBlockProtection(
+    span<BlockProtection, protectionBlocks> protection) const {
+  return doReadAllBlockProtection(protection, DS28E22);
+}
+
+error_code DS28E22::loadSecret(bool lock) { return doLoadSecret(lock, false); }
+
+error_code DS28E22::computeSecret(int pageNum, bool lock) {
+  return doComputeSecret(pageNum, lock, false);
+}
+
+const int DS28EL25::memoryPages;
+const int DS28EL25::protectionBlocks;
+
+error_code DS28EL25::writeScratchpad(Page::const_span data) {
+  return doWriteScratchpad(data, DS28E25);
+}
+
+error_code DS28EL25::readScratchpad(Page::span 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,
+                                      Segment::const_span newData,
+                                      Page::const_span mac) {
+  return doWriteAuthSegment(pageNum, segmentNum, newData, mac, DS28E25);
+}
+
+error_code DS28EL25::continueWriteAuthSegment(Segment::const_span newData,
+                                              Page::const_span mac) {
+  return doContinueWriteAuthSegment(newData, mac, DS28E25);
+}
+
+error_code DS28EL25::readAllBlockProtection(
+    span<BlockProtection, protectionBlocks> protection) const {
+  return doReadAllBlockProtection(protection, 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 MaximInterfaceDevices
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS28E15_22_25.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,909 @@
+/*******************************************************************************
+* 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 MaximInterfaceDevices_DS28E15_22_25
+#define MaximInterfaceDevices_DS28E15_22_25
+
+#include <stdint.h>
+#include <MaximInterfaceCore/Algorithm.hpp>
+#include <MaximInterfaceCore/array_span.hpp>
+#include <MaximInterfaceCore/ManId.hpp>
+#include <MaximInterfaceCore/OneWireMaster.hpp>
+#include <MaximInterfaceCore/RomId.hpp>
+#include <MaximInterfaceCore/SelectRom.hpp>
+#include <MaximInterfaceCore/Sleep.hpp>
+#include "Config.hpp"
+
+namespace MaximInterfaceDevices {
+
+/// @brief
+/// 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 Core::array_span<uint_least8_t, 4> Segment;
+
+  /// Holds the contents of a device memory page.
+  typedef Core::array_span<uint_least8_t, 32> Page;
+
+  /// Number of segments per page.
+  static const int segmentsPerPage = Page::size / Segment::size;
+
+  /// Container for the device personality.
+  struct Personality {
+    uint_least8_t PB1;
+    uint_least8_t PB2;
+    Core::ManId::array manId;
+
+    bool secretLocked() const { return PB2 & 0x01; }
+  };
+
+  // Represents the status of a memory protection block.
+  class BlockProtection;
+
+  // Format data to hash for an Authenticated Write to a memory segment.
+  class SegmentWriteMacData;
+
+  // Format data to hash for an Authenticated Write to a memory protection block.
+  class ProtectionWriteMacData;
+
+  // Format data to hash for device authentication or computing the next secret
+  // from the existing secret.
+  class AuthenticationData;
+
+  void setSleep(Core::Sleep & sleep) { this->sleep = &sleep; }
+
+  void setMaster(Core::OneWireMaster & master) { this->master = &master; }
+
+  void setSelectRom(const Core::SelectRom & selectRom) {
+    this->selectRom = selectRom;
+  }
+
+  // Const member functions should not affect the state of the memory,
+  // block protection, or secret on the device.
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readSegment(int pageNum, int segmentNum, Segment::span data) const;
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  continueReadSegment(Segment::span data) const;
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeSegment(int pageNum, int segmentNum, Segment::const_span data);
+
+  /// @brief Continue an in-progress Write Memory command.
+  /// @param[in] data Data to write to the memory segment.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  continueWriteSegment(Segment::const_span data);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readPage(int pageNum, Page::span rdbuf) const;
+
+  /// @brief Continue an in-progress readPageOperation.
+  /// @param[out] rdbuf Buffer to read data from the page into.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  continueReadPage(Page::span rdbuf) const;
+
+  /// @brief
+  /// 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeReadPageMac(int pageNum, bool anon, Page::span mac) const;
+
+  /// @brief
+  /// Update the status of a memory protection block using the
+  /// Write Page Protection command.
+  /// @param protection
+  /// Desired protection status for the block.
+  /// It is not possible to disable existing protections.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeBlockProtection(BlockProtection protection);
+
+  /// @brief
+  /// Update the status of a memory protection block using the
+  /// Authenticated Write Page Protection command.
+  /// @param newProtection New protection status to write.
+  /// @param[in] mac Write MAC computed for this operation.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeAuthBlockProtection(BlockProtection newProtection, Page::const_span mac);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code loadSecret(bool lock);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code computeSecret(int pageNum,
+                                                              bool lock);
+
+  /// @brief Read the personality bytes using the Read Status command.
+  /// @param[out] personality Receives personality read from device.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readPersonality(Personality & personality) const;
+
+  MaximInterfaceDevices_EXPORT static const Core::error_category &
+  errorCategory();
+
+protected:
+  enum Variant { DS28E15, DS28E22, DS28E25 };
+
+  DS28E15_22_25(Core::Sleep & sleep, Core::OneWireMaster & master,
+                const Core::SelectRom & selectRom)
+      : selectRom(selectRom), master(&master), sleep(&sleep) {}
+
+  ~DS28E15_22_25() {}
+
+  Core::error_code doWriteScratchpad(Page::const_span data, Variant variant);
+
+  Core::error_code doReadScratchpad(Page::span data, Variant variant) const;
+
+  Core::error_code doReadBlockProtection(int blockNum,
+                                         BlockProtection & protection,
+                                         Variant variant) const;
+
+  Core::error_code doWriteAuthSegment(int pageNum, int segmentNum,
+                                      Segment::const_span newData,
+                                      Page::const_span mac, Variant variant);
+
+  Core::error_code doContinueWriteAuthSegment(Segment::const_span newData,
+                                              Page::const_span mac,
+                                              Variant variant);
+
+  Core::error_code
+  doReadAllBlockProtection(Core::span<BlockProtection> protection,
+                           Variant variant) const;
+
+  Core::error_code doLoadSecret(bool lock, bool lowPower);
+
+  Core::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,
+  };
+
+  Core::error_code doWriteAuthSegment(Segment::const_span newData,
+                                      Page::const_span mac, Variant variant,
+                                      bool continuing);
+
+  Core::error_code
+  writeCommandWithCrc(Command command, uint_least8_t parameter,
+                      Core::OneWireMaster::Level level =
+                          Core::OneWireMaster::NormalLevel) const;
+
+  Core::SelectRom selectRom;
+  Core::OneWireMaster * master;
+  Core::Sleep * sleep;
+};
+
+inline Core::error_code make_error_code(DS28E15_22_25::ErrorValue e) {
+  return Core::error_code(e, DS28E15_22_25::errorCategory());
+}
+
+/// 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(Core::Sleep & sleep, Core::OneWireMaster & master,
+           const Core::SelectRom & selectRom)
+      : DS28E15_22_25(sleep, master, selectRom) {}
+
+  /// @brief Perform Write Scratchpad operation on the device.
+  /// @param[in] data Data to write to the scratchpad.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeScratchpad(Page::const_span data);
+
+  /// @brief Perform a Read Scratchpad operation on the device.
+  /// @param[out] data Buffer to read data from the scratchpad into.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readScratchpad(Page::span data) const;
+
+  /// @brief
+  /// 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readBlockProtection(int blockNum, BlockProtection & protection) const;
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeAuthSegment(int pageNum, int segmentNum, Segment::const_span newData,
+                   Page::const_span mac);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  continueWriteAuthSegment(Segment::const_span newData, Page::const_span mac);
+
+  /// @brief
+  /// Read the status of all memory protection blocks using the Read Status command.
+  /// @param[out] protection Receives protection statuses read from device.
+  MaximInterfaceDevices_EXPORT Core::error_code readAllBlockProtection(
+      Core::span<BlockProtection, protectionBlocks> protection) const;
+};
+
+/// Interface to the DS28E15 authenticator.
+class DS28E15 : public DS28EL15 {
+public:
+  DS28E15(Core::Sleep & sleep, Core::OneWireMaster & master,
+          const Core::SelectRom & selectRom)
+      : DS28EL15(sleep, master, selectRom) {}
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code loadSecret(bool lock);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::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(Core::Sleep & sleep, Core::OneWireMaster & master,
+           const Core::SelectRom & selectRom)
+      : DS28E15_22_25(sleep, master, selectRom) {}
+
+  /// @brief Perform Write Scratchpad operation on the device.
+  /// @param[in] data Data to write to the scratchpad.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeScratchpad(Page::const_span data);
+
+  /// @brief Perform a Read Scratchpad operation on the device.
+  /// @param[out] data Buffer to read data from the scratchpad into.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readScratchpad(Page::span data) const;
+
+  /// @brief
+  /// 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readBlockProtection(int blockNum, BlockProtection & protection) const;
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeAuthSegment(int pageNum, int segmentNum, Segment::const_span newData,
+                   Page::const_span mac);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  continueWriteAuthSegment(Segment::const_span newData, Page::const_span mac);
+
+  /// @brief
+  /// Read the status of all memory protection blocks using the Read Status command.
+  /// @param[out] protection Receives protection statuses read from device.
+  MaximInterfaceDevices_EXPORT Core::error_code readAllBlockProtection(
+      Core::span<BlockProtection, protectionBlocks> protection) const;
+};
+
+/// Interface to the DS28E22 authenticator.
+class DS28E22 : public DS28EL22 {
+public:
+  DS28E22(Core::Sleep & sleep, Core::OneWireMaster & master,
+          const Core::SelectRom & selectRom)
+      : DS28EL22(sleep, master, selectRom) {}
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code loadSecret(bool lock);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::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(Core::Sleep & sleep, Core::OneWireMaster & master,
+           const Core::SelectRom & selectRom)
+      : DS28E15_22_25(sleep, master, selectRom) {}
+
+  /// @brief Perform Write Scratchpad operation on the device.
+  /// @param[in] data Data to write to the scratchpad.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeScratchpad(Page::const_span data);
+
+  /// @brief Perform a Read Scratchpad operation on the device.
+  /// @param[out] data Buffer to read data from the scratchpad into.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readScratchpad(Page::span data) const;
+
+  /// @brief
+  /// 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.
+  MaximInterfaceDevices_EXPORT Core::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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeAuthSegment(int pageNum, int segmentNum, Segment::const_span newData,
+                   Page::const_span mac);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  continueWriteAuthSegment(Segment::const_span newData, Page::const_span mac);
+
+  /// @brief
+  /// Read the status of all memory protection blocks using the Read Status command.
+  /// @param[out] protection Receives protection statuses read from device.
+  MaximInterfaceDevices_EXPORT Core::error_code readAllBlockProtection(
+      Core::span<BlockProtection, protectionBlocks> protection) const;
+};
+
+/// Interface to the DS28E25 authenticator.
+class DS28E25 : public DS28EL25 {
+public:
+  DS28E25(Core::Sleep & sleep, Core::OneWireMaster & master,
+          const Core::SelectRom & selectRom)
+      : DS28EL25(sleep, master, selectRom) {}
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code loadSecret(bool lock);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code computeSecret(int pageNum,
+                                                              bool lock);
+};
+
+/// Represents the status of a memory protection block.
+class DS28E15_22_25::BlockProtection {
+public:
+  explicit BlockProtection(uint_least8_t status = 0x00) : status(status) {}
+
+  /// Get the byte representation used by the device.
+  uint_least8_t statusByte() const { return status; }
+
+  /// Set the byte representation used by the device.
+  BlockProtection & setStatusByte(uint_least8_t status) {
+    this->status = status;
+    return *this;
+  }
+
+  /// Get the Block Number which is indexed from zero.
+  int blockNum() const { return (status & blockNumMask); }
+
+  /// Set the Block Number which is indexed from zero.
+  MaximInterfaceDevices_EXPORT BlockProtection & setBlockNum(int blockNum);
+
+  /// @brief Get the Read Protection status.
+  /// @returns True if Read Protection is enabled.
+  bool readProtection() const {
+    return ((status & readProtectionMask) == readProtectionMask);
+  }
+
+  /// Set the Read Protection status.
+  MaximInterfaceDevices_EXPORT BlockProtection &
+  setReadProtection(bool readProtection);
+
+  /// @brief Get the Write Protection status.
+  /// @returns True if Write Protection is enabled.
+  bool writeProtection() const {
+    return ((status & writeProtectionMask) == writeProtectionMask);
+  }
+
+  /// Set the Write Protection status.
+  MaximInterfaceDevices_EXPORT BlockProtection &
+  setWriteProtection(bool writeProtection);
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT BlockProtection &
+  setEepromEmulation(bool eepromEmulation);
+
+  /// @brief Get the Authentication Protection status.
+  /// @returns True if Authentication Protection is enabled.
+  bool authProtection() const {
+    return ((status & authProtectionMask) == authProtectionMask);
+  }
+
+  /// Set the Authentication Protection status.
+  MaximInterfaceDevices_EXPORT BlockProtection &
+  setAuthProtection(bool authProtection);
+
+  /// @brief Check if no protection options are enabled.
+  /// @returns True if no protection options are enabled.
+  MaximInterfaceDevices_EXPORT bool noProtection() const;
+
+private:
+  static const unsigned int readProtectionMask = 0x80,
+                            writeProtectionMask = 0x40,
+                            eepromEmulationMask = 0x20,
+                            authProtectionMask = 0x10, blockNumMask = 0x0F;
+  uint_least8_t status;
+};
+
+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);
+}
+
+/// Format data to hash for an Authenticated Write to a memory segment.
+class DS28E15_22_25::SegmentWriteMacData {
+public:
+  typedef Core::array_span<uint_least8_t, 20> Result;
+
+  SegmentWriteMacData() : result_() {}
+
+  /// Formatted data result.
+  Result::const_span result() const { return result_; }
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() {
+    return make_span(result_).subspan<romIdIdx, Core::RomId::size>();
+  }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const {
+    return const_cast<SegmentWriteMacData &>(*this).romId();
+  }
+
+  /// Set ROM ID.
+  SegmentWriteMacData & setRomId(Core::RomId::const_span romId) {
+    copy(romId, this->romId());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() {
+    return make_span(result_).subspan<manIdIdx, Core::ManId::size>();
+  }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const {
+    return const_cast<SegmentWriteMacData &>(*this).manId();
+  }
+
+  /// Set MAN ID.
+  SegmentWriteMacData & setManId(Core::ManId::const_span manId) {
+    copy(manId, this->manId());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Page number for write operation.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return result_[pageNumIdx]; }
+
+  /// Set page number.
+  SegmentWriteMacData & setPageNum(int pageNum) {
+    result_[pageNumIdx] = pageNum;
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Segment number
+  /// @brief Segment number within page for write operation.
+  /// @{
+
+  /// Get segment number.
+  int segmentNum() const { return result_[segmentNumIdx]; }
+
+  /// Set segment number.
+  SegmentWriteMacData & setSegmentNum(int segmentNum) {
+    result_[segmentNumIdx] = segmentNum;
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Old data
+  /// @brief Existing data contained in the segment.
+  /// @{
+
+  /// Get mutable old data.
+  Segment::span oldData() {
+    return make_span(result_).subspan<oldDataIdx, Segment::size>();
+  }
+
+  /// Get immutable old data.
+  Segment::const_span oldData() const {
+    return const_cast<SegmentWriteMacData &>(*this).oldData();
+  }
+
+  /// Set old data.
+  SegmentWriteMacData & setOldData(Segment::const_span oldData) {
+    copy(oldData, this->oldData());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name New data
+  /// @brief New data to write to the segment.
+  /// @{
+
+  /// Get mutable new data.
+  Segment::span newData() {
+    return make_span(result_).subspan<newDataIdx, Segment::size>();
+  }
+
+  /// Get immutable new data.
+  Segment::const_span newData() const {
+    return const_cast<SegmentWriteMacData &>(*this).newData();
+  }
+
+  /// Set new data.
+  SegmentWriteMacData & setNewData(Segment::const_span newData) {
+    copy(newData, this->newData());
+    return *this;
+  }
+
+  /// @}
+
+private:
+  typedef Result::span::index_type index;
+
+  static const index romIdIdx = 0;
+  static const index manIdIdx = romIdIdx + Core::RomId::size;
+  static const index pageNumIdx = manIdIdx + Core::ManId::size;
+  static const index segmentNumIdx = pageNumIdx + 1;
+  static const index oldDataIdx = segmentNumIdx + 1;
+  static const index newDataIdx = oldDataIdx + Segment::size;
+
+  Result::array result_;
+};
+
+/// Format data to hash for an Authenticated Write to a memory protection block.
+class DS28E15_22_25::ProtectionWriteMacData {
+public:
+  typedef Core::array_span<uint_least8_t, 20> Result;
+
+  MaximInterfaceDevices_EXPORT ProtectionWriteMacData();
+
+  /// Formatted data result.
+  Result::const_span result() const { return result_; }
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() {
+    return make_span(result_).subspan<romIdIdx, Core::RomId::size>();
+  }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const {
+    return const_cast<ProtectionWriteMacData &>(*this).romId();
+  }
+
+  /// Set ROM ID.
+  ProtectionWriteMacData & setRomId(Core::RomId::const_span romId) {
+    copy(romId, this->romId());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() {
+    return make_span(result_).subspan<manIdIdx, Core::ManId::size>();
+  }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const {
+    return const_cast<ProtectionWriteMacData &>(*this).manId();
+  }
+
+  /// Set MAN ID.
+  ProtectionWriteMacData & setManId(Core::ManId::const_span manId) {
+    copy(manId, this->manId());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Old protection
+  /// @brief Existing protection status in device.
+  /// @{
+
+  /// Get old protection.
+  BlockProtection oldProtection() const { return oldProtection_; }
+
+  /// Set old protection.
+  MaximInterfaceDevices_EXPORT ProtectionWriteMacData &
+  setOldProtection(BlockProtection oldProtection);
+
+  /// @}
+
+  /// @name New protection
+  /// @brief New protection status to write.
+  /// @{
+
+  /// Get new protection.
+  BlockProtection newProtection() const { return newProtection_; }
+
+  /// Set new protection.
+  MaximInterfaceDevices_EXPORT ProtectionWriteMacData &
+  setNewProtection(BlockProtection newProtection);
+
+  /// @}
+
+private:
+  typedef Result::span::index_type index;
+
+  static const index romIdIdx = 0;
+  static const index manIdIdx = romIdIdx + Core::RomId::size;
+  static const index blockNumIdx = manIdIdx + Core::ManId::size;
+  static const index oldProtectionIdx = blockNumIdx + 2;
+  static const index newProtectionIdx = oldProtectionIdx + 4;
+
+  Result::array result_;
+  BlockProtection oldProtection_;
+  BlockProtection newProtection_;
+};
+
+/// @brief
+/// Format data to hash for device authentication or computing the next secret
+/// from the existing secret.
+class DS28E15_22_25::AuthenticationData {
+public:
+  typedef Core::array_span<uint_least8_t, 76> Result;
+
+  AuthenticationData() : result_() {}
+
+  /// Formatted data result.
+  Result::const_span result() const { return result_; }
+
+  /// @name Page
+  /// @brief Data from a device memory page.
+  /// @{
+
+  /// Get mutable page.
+  Page::span page() {
+    return make_span(result_).subspan<pageIdx, Page::size>();
+  }
+
+  /// Get immutable page.
+  Page::const_span page() const {
+    return const_cast<AuthenticationData &>(*this).page();
+  }
+
+  /// Set page.
+  AuthenticationData & setPage(Page::const_span page) {
+    copy(page, this->page());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Scratchpad
+  /// @brief
+  /// Data from device scratchpad used as a random challenge in device
+  /// authentication and a partial secret in secret computation.
+  /// @{
+
+  /// Get mutable scratchpad.
+  Page::span scratchpad() {
+    return make_span(result_).subspan<scratchpadIdx, Page::size>();
+  }
+
+  /// Get immutable scratchpad.
+  Page::const_span scratchpad() const {
+    return const_cast<AuthenticationData &>(*this).scratchpad();
+  }
+
+  /// Set scratchpad.
+  AuthenticationData & setScratchpad(Page::const_span scratchpad) {
+    copy(scratchpad, this->scratchpad());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() {
+    return make_span(result_).subspan<romIdIdx, Core::RomId::size>();
+  }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const {
+    return const_cast<AuthenticationData &>(*this).romId();
+  }
+
+  /// Set ROM ID.
+  AuthenticationData & setRomId(Core::RomId::const_span romId) {
+    copy(romId, this->romId());
+    return *this;
+  }
+
+  /// Set ROM ID for use in anonymous mode.
+  MaximInterfaceDevices_EXPORT AuthenticationData & setAnonymousRomId();
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() {
+    return make_span(result_).subspan<manIdIdx, Core::ManId::size>();
+  }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const {
+    return const_cast<AuthenticationData &>(*this).manId();
+  }
+
+  /// Set MAN ID.
+  AuthenticationData & setManId(Core::ManId::const_span manId) {
+    copy(manId, this->manId());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Number of the page to use data from.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return result_[pageNumIdx]; }
+
+  /// Set page number.
+  AuthenticationData & setPageNum(int pageNum) {
+    result_[pageNumIdx] = pageNum;
+    return *this;
+  }
+
+  /// @}
+
+private:
+  typedef Result::span::index_type index;
+
+  static const index pageIdx = 0;
+  static const index scratchpadIdx = pageIdx + Page::size;
+  static const index romIdIdx = scratchpadIdx + Page::size;
+  static const index manIdIdx = romIdIdx + Core::RomId::size;
+  static const index pageNumIdx = manIdIdx + Core::ManId::size;
+
+  Result::array result_;
+};
+
+} // namespace MaximInterfaceDevices
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS28E16.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,293 @@
+/*******************************************************************************
+* Copyright (C) 2018 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 <algorithm>
+#include <MaximInterfaceCore/Error.hpp>
+#include "DS28E16.hpp"
+
+namespace MaximInterfaceDevices {
+
+using namespace Core;
+using std::copy;
+using std::fill;
+
+static const int readMemoryTimeMs = 5;
+static const int writeMemoryTimeMs = 60;
+static const int shortWriteMemoryTimeMs = 15;
+static const int computationTimeMs = 15;
+
+const int DS28E16::decrementCounterPage;
+const int DS28E16::masterSecretPage;
+const int DS28E16::memoryPages;
+
+error_code DS28E16::writeMemory(int pageNum, Page::const_span page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t request[2 + Page::size];
+  request[0] = 0x96;
+  request[1] = pageNum;
+  copy(page.begin(), page.end(), request + 2);
+  return runCommand(request, writeMemoryTimeMs);
+}
+
+error_code DS28E16::readMemory(int pageNum, Page::span page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[1 + Page::size * 2];
+  buffer[0] = 0x44;
+  buffer[1] = pageNum;
+  span<uint_least8_t> response(buffer);
+  const error_code result =
+      runCommand(make_span(buffer, 2), readMemoryTimeMs, response);
+  if (!result) {
+    response = response.first(Page::size);
+    copy(response.begin(), response.end(), page.begin());
+  }
+  return result;
+}
+
+error_code DS28E16::readStatus(Status & status) {
+  uint_least8_t buffer[1 + Status::PageProtectionList::csize + 2];
+  buffer[0] = 0xAA;
+  span<uint_least8_t> response(buffer);
+  const error_code result =
+      runCommand(make_span(buffer, 1), readMemoryTimeMs, response);
+  if (!result) {
+    span<uint_least8_t>::const_iterator responseIt = response.begin();
+    for (Status::PageProtectionList::iterator it =
+             status.pageProtection.begin();
+         it != status.pageProtection.end(); ++it) {
+      *it = *responseIt;
+      ++responseIt;
+    }
+    status.manId = *responseIt;
+    ++responseIt;
+    status.deviceVersion = *responseIt;
+  }
+  return result;
+}
+
+error_code DS28E16::setPageProtection(int pageNum,
+                                      const PageProtection & protection) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const uint_least8_t request[] = {
+      0xC3, static_cast<uint_least8_t>(pageNum),
+      static_cast<uint_least8_t>(protection.to_ulong())};
+  return runCommand(request, shortWriteMemoryTimeMs);
+}
+
+error_code
+DS28E16::computeAndReadPageAuthentication(int pageNum, bool anonymous,
+                                          DoublePage::const_span challenge,
+                                          DoublePage::span hmac) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const size_t requestSize = 3 + DoublePage::size;
+  const size_t responseSize = 1 + DoublePage::size;
+  uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
+  buffer[0] = 0xA5;
+  buffer[1] = pageNum;
+  if (anonymous) {
+    buffer[1] |= 0xE0;
+  }
+  buffer[2] = 0x02;
+  copy(challenge.begin(), challenge.end(), buffer + 3);
+  span<uint_least8_t> response(buffer, responseSize);
+  const error_code result =
+      runCommand(make_span(buffer, requestSize), computationTimeMs, response);
+  if (!result) {
+    copy(response.begin(), response.end(), hmac.begin());
+  }
+  return result;
+}
+
+error_code DS28E16::computeSecret(int bindingDataPageNum,
+                                  bool constantBindingData, bool anonymous,
+                                  DoublePage::const_span partialSecret) {
+  if (bindingDataPageNum < 0 || bindingDataPageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t request[3 + DoublePage::size];
+  request[0] = 0x3C;
+  request[1] = bindingDataPageNum;
+  if (constantBindingData) {
+    request[1] |= 0x04;
+  }
+  if (anonymous) {
+    request[1] |= 0xE0;
+  }
+  request[2] = 0x08;
+  copy(partialSecret.begin(), partialSecret.end(), request + 3);
+  return runCommand(request, computationTimeMs);
+}
+
+error_code DS28E16::decrementCounter() {
+  const uint_least8_t request = 0xC9;
+  return runCommand(make_span(&request, 1), writeMemoryTimeMs);
+}
+
+error_code DS28E16::lockOutDisableDevice() {
+  const DisableDevicePassword::array password = {};
+  return disableDevice(LockOutDisableDevice, password);
+}
+
+error_code
+DS28E16::setDisableDevicePassword(DisableDevicePassword::const_span password) {
+  return disableDevice(SetDisableDevicePassword, password);
+}
+
+error_code DS28E16::disableDevice(DisableDevicePassword::const_span password) {
+  return disableDevice(DisableDevice, password);
+}
+
+error_code DS28E16::disableDevice(DisableDeviceOperation operation,
+                                  DisableDevicePassword::const_span password) {
+  const uint_least8_t request[] = {
+      0x33,        static_cast<uint_least8_t>(operation),
+      password[0], password[1],
+      0x71,        0x35,
+      0x0E,        0xAC,
+      0x95,        0xF8};
+  return runCommand(request, shortWriteMemoryTimeMs);
+}
+
+error_code DS28E16::runCommand(span<const uint_least8_t> request, int delayTime,
+                               span<uint_least8_t> & response) {
+  const span<const uint_least8_t>::index_type responseInputSize =
+      response.size();
+  error_code result = doRunCommand(request, delayTime, response);
+  if (result) {
+    return result;
+  }
+  if (response.empty()) {
+    return make_error_code(InvalidResponseError);
+  }
+  // Parse command result byte.
+  switch (response[0]) {
+  case 0xAA:
+    // Success response.
+    if (response.size() != responseInputSize) {
+      result = make_error_code(InvalidResponseError);
+    }
+    break;
+
+  case 0x00:
+    result = make_error_code(AuthenticationError);
+    break;
+
+  default:
+    result.assign(response[0], errorCategory());
+    break;
+  }
+  response = response.subspan(1);
+  return result;
+}
+
+error_code DS28E16::runCommand(span<const uint_least8_t> request,
+                               int delayTime) {
+  uint_least8_t buffer;
+  span<uint_least8_t> response(&buffer, 1);
+  return runCommand(request, delayTime, response);
+}
+
+const error_category & DS28E16::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "DS28E16"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case InvalidOperationError:
+        return "Invalid Operation Error";
+
+      case InvalidParameterError:
+        return "Invalid Parameter Error";
+
+      case InvalidSequenceError:
+        return "Invalid Sequence Error";
+
+      case InternalError:
+        return "Internal Error";
+
+      case DeviceDisabledError:
+        return "Device Disabled Error";
+
+      case AuthenticationError:
+        return "Authentication Error";
+
+      case InvalidResponseError:
+        return "Invalid Response Error";
+      }
+      return defaultErrorMessage(condition);
+    }
+  } instance;
+  return instance;
+}
+
+error_code readManId(DS28E16 & device, uint_least8_t & manId) {
+  DS28E16::Status status;
+  const error_code result = device.readStatus(status);
+  if (!result) {
+    manId = status.manId;
+  }
+  return result;
+}
+
+DS28E16::PageAuthenticationData &
+DS28E16::PageAuthenticationData::setAnonymousRomId() {
+  fill(romId().begin(), romId().end(), 0xFF);
+  return *this;
+}
+
+DS28E16::ComputeSecretData &
+DS28E16::ComputeSecretData::setConstantBindingData(bool constantBindingData) {
+  if (constantBindingData) {
+    data.setPageNum(data.pageNum() | constantBindingDataMask);
+    fill(bindingData().begin(), bindingData().end(), 0);
+  } else {
+    data.setPageNum(data.pageNum() & ~constantBindingDataMask);
+  }
+  return *this;
+}
+
+} // namespace MaximInterfaceDevices
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS28E16.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,458 @@
+/*******************************************************************************
+* Copyright (C) 2018 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 MaximInterfaceDevices_DS28E16
+#define MaximInterfaceDevices_DS28E16
+
+#include <stdint.h>
+#include <MaximInterfaceCore/Algorithm.hpp>
+#include <MaximInterfaceCore/array_span.hpp>
+#include <MaximInterfaceCore/FlagSet.hpp>
+#include <MaximInterfaceCore/RomId.hpp>
+#include <MaximInterfaceCore/RunCommand.hpp>
+#include <MaximInterfaceCore/system_error.hpp>
+#include "Config.hpp"
+
+namespace MaximInterfaceDevices {
+
+class DS28E16 {
+public:
+  /// Device command results.
+  enum ErrorValue {
+    InvalidOperationError = 0x55,
+    InvalidParameterError = 0x77,
+    InvalidSequenceError = 0x33,
+    InternalError = 0x22,
+    DeviceDisabledError = 0x88,
+    AuthenticationError = 0x100,
+    InvalidResponseError ///< Command response does not match expected format.
+  };
+
+  /// @name Device memory pages
+  /// @{
+
+  static const int decrementCounterPage = 2;
+  static const int masterSecretPage = 3;
+
+  /// @}
+
+  static const int memoryPages = 4;
+
+  /// Holds a device memory page.
+  typedef Core::array_span<uint_least8_t, 16> Page;
+
+  /// Holds a Challenge, Partial Secret, or HMAC.
+  typedef Core::array_span<uint_least8_t, 32> DoublePage;
+
+  /// Holds a password used to disable the device.
+  typedef Core::array_span<uint_least8_t, 2> DisableDevicePassword;
+
+  // Format page authentication input data.
+  class PageAuthenticationData;
+
+  // Format compute secret input data.
+  class ComputeSecretData;
+
+  /// Page protection types.
+  enum PageProtectionType {
+    RP = 0x01, ///< Read protection.
+    WP = 0x02, ///< Write protection.
+    DC = 0x08  ///< Decrement counter.
+  };
+  typedef Core::FlagSet<PageProtectionType, 4> PageProtection;
+
+  struct Status {
+    typedef Core::array<PageProtection, memoryPages> PageProtectionList;
+
+    PageProtectionList pageProtection;
+    uint_least8_t manId;
+    uint_least8_t deviceVersion;
+  };
+
+  explicit DS28E16(const Core::RunCommand & runCommand)
+      : doRunCommand(runCommand) {}
+
+  void setRunCommand(const Core::RunCommand & runCommand) {
+    doRunCommand = runCommand;
+  }
+
+  /// @brief Write memory with no protection.
+  /// @param pageNum Number of page to write.
+  /// @param page Data to write.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeMemory(int pageNum, Page::const_span page);
+
+  /// @brief Read memory with no protection.
+  /// @param pageNum Number of page to read.
+  /// @param[out] page Data that was read.
+  MaximInterfaceDevices_EXPORT Core::error_code readMemory(int pageNum,
+                                                           Page::span page);
+
+  /// @brief Reads the current status of the device.
+  /// @param[out] status Status that was read.
+  MaximInterfaceDevices_EXPORT Core::error_code readStatus(Status & status);
+
+  /// @brief Set the protection settings of a page.
+  /// @param pageNum Number of page to write.
+  /// @param protection Protection to write.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  setPageProtection(int pageNum, const PageProtection & protection);
+
+  /// @brief Compute and read page authentication with HMAC.
+  /// @param pageNum Number of page to authenticate.
+  /// @param anonymous True to disable use of ROM ID in computation.
+  /// @param challenge Random challenge used to prevent replay attacks.
+  /// @param[out] hmac Computed page HMAC.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeAndReadPageAuthentication(int pageNum, bool anonymous,
+                                   DoublePage::const_span challenge,
+                                   DoublePage::span hmac);
+
+  /// Decrement the decrement-only counter.
+  MaximInterfaceDevices_EXPORT Core::error_code decrementCounter();
+
+  /// Set password that will be subsequently used to disable the device.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  setDisableDevicePassword(DisableDevicePassword::const_span password);
+
+  /// @brief Lock-out all disable functionality for the device.
+  /// @note Only allowed prior to setting password.
+  MaximInterfaceDevices_EXPORT Core::error_code lockOutDisableDevice();
+
+  /// Permanently disable the device.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  disableDevice(DisableDevicePassword::const_span password);
+
+  /// @brief
+  /// Compute a derivative secret for authentication from the Master Secret.
+  /// @param bindingDataPageNum Page number for Binding Data.
+  /// @param constantBindingData
+  /// Use constant Binding Data instead of Binding Data from the selected page.
+  /// @param anonymous True to disable use of ROM ID in computation.
+  /// @param partialSecret Partial secret to use in computation.
+  /// @note
+  /// This command should be executed prior to the
+  /// Compute and Read Page Authentication command.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeSecret(int bindingDataPageNum, bool constantBindingData,
+                bool anonymous, DoublePage::const_span partialSecret);
+
+  MaximInterfaceDevices_EXPORT static const Core::error_category &
+  errorCategory();
+
+protected:
+  MaximInterfaceDevices_EXPORT Core::error_code
+  runCommand(Core::span<const uint_least8_t> request, int delayTime,
+             Core::span<uint_least8_t> & response);
+
+  MaximInterfaceDevices_EXPORT Core::error_code
+  runCommand(Core::span<const uint_least8_t> request, int delayTime);
+
+private:
+  enum DisableDeviceOperation {
+    SetDisableDevicePassword = 0x0F,
+    LockOutDisableDevice = 0x05,
+    DisableDevice = 0x00
+  };
+
+  Core::error_code disableDevice(DisableDeviceOperation operation,
+                                 DisableDevicePassword::const_span password);
+
+  Core::RunCommand doRunCommand;
+};
+
+inline Core::error_code make_error_code(DS28E16::ErrorValue e) {
+  return Core::error_code(e, DS28E16::errorCategory());
+}
+
+/// @brief Read the device MAN ID using the Read Status command.
+/// @param device Device to read.
+/// @param[out] manId Read MAN ID valid when operation is successful.
+MaximInterfaceDevices_EXPORT Core::error_code readManId(DS28E16 & device,
+                                                        uint_least8_t & manId);
+
+/// Format page authentication input data.
+class DS28E16::PageAuthenticationData {
+public:
+  typedef Core::array_span<uint_least8_t, Core::RomId::size + 2 * Page::size +
+                                              DoublePage::size + 3>
+      Result;
+
+  PageAuthenticationData() : result_() {}
+
+  /// Formatted data result.
+  Result::const_span result() const { return result_; }
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() {
+    return make_span(result_).subspan<romIdIdx, Core::RomId::size>();
+  }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const {
+    return const_cast<PageAuthenticationData &>(*this).romId();
+  }
+
+  /// Set ROM ID.
+  PageAuthenticationData & setRomId(Core::RomId::const_span romId) {
+    copy(romId, this->romId());
+    return *this;
+  }
+
+  /// Set ROM ID for use in anonymous mode.
+  MaximInterfaceDevices_EXPORT PageAuthenticationData & setAnonymousRomId();
+
+  /// @}
+
+  /// @name Page
+  /// @brief Data from a device memory page.
+  /// @{
+
+  /// Get mutable page.
+  Page::span page() {
+    return make_span(result_).subspan<pageIdx, Page::size>();
+  }
+
+  /// Get immutable page.
+  Page::const_span page() const {
+    return const_cast<PageAuthenticationData &>(*this).page();
+  }
+
+  /// Set page.
+  PageAuthenticationData & setPage(Page::const_span page) {
+    copy(page, this->page());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Challenge.
+  /// @brief Random challenge used to prevent replay attacks.
+  /// @{
+
+  /// Get mutable Challenge.
+  DoublePage::span challenge() {
+    return make_span(result_).subspan<challengeIdx, DoublePage::size>();
+  }
+
+  /// Get immutable Challenge.
+  DoublePage::const_span challenge() const {
+    return const_cast<PageAuthenticationData &>(*this).challenge();
+  }
+
+  /// Set Challenge.
+  PageAuthenticationData & setChallenge(DoublePage::const_span challenge) {
+    copy(challenge, this->challenge());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Number of the page to use data from.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return result_[pageNumIdx]; }
+
+  /// Set page number.
+  PageAuthenticationData & setPageNum(int pageNum) {
+    result_[pageNumIdx] = pageNum;
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  uint_least8_t & manId() { return result_[manIdIdx]; }
+
+  /// Get immutable MAN ID.
+  uint_least8_t manId() const {
+    return const_cast<PageAuthenticationData &>(*this).manId();
+  }
+
+  /// Set MAN ID.
+  PageAuthenticationData & setManId(uint_least8_t manId) {
+    this->manId() = manId;
+    return *this;
+  }
+
+  /// @}
+
+private:
+  typedef Result::span::index_type index;
+
+  static const index romIdIdx = 0;
+  static const index pageIdx = romIdIdx + Core::RomId::size;
+  static const index challengeIdx = pageIdx + 2 * Page::size;
+  static const index pageNumIdx = challengeIdx + DoublePage::size;
+  static const index manIdIdx = pageNumIdx + 1;
+
+  Result::array result_;
+};
+
+/// Format compute secret input data.
+class DS28E16::ComputeSecretData {
+public:
+  typedef PageAuthenticationData::Result Result;
+
+  ComputeSecretData() : data() {
+    data.setPageNum(0x80 | constantBindingDataMask);
+  }
+
+  /// Formatted data result.
+  Result::const_span result() const { return data.result(); }
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() { return data.romId(); }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const { return data.romId(); }
+
+  /// Set ROM ID.
+  ComputeSecretData & setRomId(Core::RomId::const_span romId) {
+    data.setRomId(romId);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Binding Data
+  /// @brief Binding Data contained in the selected page.
+  /// @{
+
+  /// Get mutable Binding Data.
+  Page::span bindingData() { return data.page(); }
+
+  /// Get immutable Binding Data.
+  Page::const_span bindingData() const { return data.page(); }
+
+  /// Set Binding Data.
+  ComputeSecretData & setBindingData(Page::const_span bindingData) {
+    data.setPage(bindingData);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Constant Binding Data
+  /// @brief
+  /// Use constant Binding Data instead of Binding Data from the selected page.
+  /// @{
+
+  /// Get Constant Binding Data.
+  bool constantBindingData() const {
+    return (data.pageNum() & constantBindingDataMask) ==
+           constantBindingDataMask;
+  }
+
+  /// Set Constant Binding Data.
+  MaximInterfaceDevices_EXPORT ComputeSecretData &
+  setConstantBindingData(bool constantBindingData);
+
+  /// @}
+
+  /// @name Partial Secret
+  /// @brief Partial Secret used for customization.
+  /// @{
+
+  /// Get mutable Partial Secret.
+  DoublePage::span partialSecret() { return data.challenge(); }
+
+  /// Get immutable Partial Secret.
+  DoublePage::const_span partialSecret() const { return data.challenge(); }
+
+  /// Set Partial Secret.
+  ComputeSecretData & setPartialSecret(DoublePage::const_span partialSecret) {
+    data.setChallenge(partialSecret);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Binding Data page number
+  /// @{
+
+  /// Get Binding Data page number.
+  int bindingDataPageNum() const {
+    return data.pageNum() & bindingDataPageNumMask;
+  }
+
+  /// Set Binding Data page number.
+  ComputeSecretData & setBindingDataPageNum(int bindingDataPageNum) {
+    data.setPageNum((bindingDataPageNum & bindingDataPageNumMask) |
+                    (data.pageNum() & ~bindingDataPageNumMask));
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  uint_least8_t & manId() { return data.manId(); }
+
+  /// Get immutable MAN ID.
+  uint_least8_t manId() const { return data.manId(); }
+
+  /// Set MAN ID.
+  ComputeSecretData & setManId(uint_least8_t manId) {
+    data.setManId(manId);
+    return *this;
+  }
+
+  /// @}
+
+private:
+  static const unsigned int bindingDataPageNumMask = 0x03;
+  static const unsigned int constantBindingDataMask = 0x04;
+
+  PageAuthenticationData data;
+};
+
+} // namespace MaximInterfaceDevices
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS28E17.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,272 @@
+/*******************************************************************************
+* 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 <MaximInterfaceCore/crc.hpp>
+#include <MaximInterfaceCore/Error.hpp>
+#include <MaximInterfaceCore/OneWireMaster.hpp>
+#include "DS28E17.hpp"
+
+namespace MaximInterfaceDevices {
+
+using namespace Core;
+
+error_code DS28E17::writeDataWithStop(uint_least8_t I2C_addr,
+                                      span<const uint_least8_t> data,
+                                      uint_least8_t * wr_status) {
+  return sendPacket(WriteDataWithStopCmd, &I2C_addr, data,
+                    span<uint_least8_t>(), wr_status);
+}
+
+error_code DS28E17::writeDataNoStop(uint_least8_t I2C_addr,
+                                    span<const uint_least8_t> data,
+                                    uint_least8_t * wr_status) {
+  return sendPacket(WriteDataNoStopCmd, &I2C_addr, data, span<uint_least8_t>(),
+                    wr_status);
+}
+
+error_code DS28E17::writeDataOnly(span<const uint_least8_t> data,
+                                  uint_least8_t * wr_status) {
+  return sendPacket(WriteDataOnlyCmd, NULL, data, span<uint_least8_t>(),
+                    wr_status);
+}
+
+error_code DS28E17::writeDataOnlyWithStop(span<const uint_least8_t> data,
+                                          uint_least8_t * wr_status) {
+  return sendPacket(WriteDataOnlyWithStopCmd, NULL, data, span<uint_least8_t>(),
+                    wr_status);
+}
+
+error_code DS28E17::writeReadDataWithStop(uint_least8_t I2C_addr,
+                                          span<const uint_least8_t> write_data,
+                                          span<uint_least8_t> read_data,
+                                          uint_least8_t * wr_status) {
+  return sendPacket(WriteReadDataWithStopCmd, &I2C_addr, write_data, read_data,
+                    wr_status);
+}
+
+error_code DS28E17::readDataWithStop(uint_least8_t I2C_addr,
+                                     span<uint_least8_t> data) {
+  return sendPacket(ReadDataWithStopCmd, &I2C_addr, span<const uint_least8_t>(),
+                    data, 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);
+  }
+  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,
+                               span<const uint_least8_t> write_data,
+                               span<uint_least8_t> read_data,
+                               uint_least8_t * wr_status) {
+  const int pollLimit = 10000;
+  const span<const uint_least8_t>::index_type maxDataLen = 255;
+
+  if ((!write_data.empty() && write_data.size() > maxDataLen) ||
+      (!read_data.empty() && read_data.size() > 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(crc16, *I2C_addr);
+    result = master->writeByte(*I2C_addr);
+    if (result) {
+      return result;
+    }
+  }
+  if (!write_data.empty()) {
+    crc16 = calculateCrc16(crc16, static_cast<uint_fast8_t>(write_data.size()));
+    result = master->writeByte(static_cast<uint_least8_t>(write_data.size()));
+    if (result) {
+      return result;
+    }
+    crc16 = calculateCrc16(crc16, write_data);
+    result = master->writeBlock(write_data);
+    if (result) {
+      return result;
+    }
+  }
+  if (!read_data.empty()) {
+    crc16 = calculateCrc16(crc16, static_cast<uint_fast8_t>(read_data.size()));
+    result = master->writeByte(static_cast<uint_least8_t>(read_data.size()));
+    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);
+  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.empty()) {
+    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.empty()) {
+    result = master->readBlock(read_data);
+  }
+  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 MaximInterfaceDevices
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS28E17.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,208 @@
+/*******************************************************************************
+* 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 MaximInterfaceDevices_DS28E17
+#define MaximInterfaceDevices_DS28E17
+
+#include <stdint.h>
+#include <MaximInterfaceCore/SelectRom.hpp>
+#include <MaximInterfaceCore/span.hpp>
+#include "Config.hpp"
+
+namespace MaximInterfaceDevices {
+
+/// @brief 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(Core::OneWireMaster & master, const Core::SelectRom & selectRom)
+      : selectRom(selectRom), master(&master) {}
+
+  void setMaster(Core::OneWireMaster & master) { this->master = &master; }
+
+  void setSelectRom(const Core::SelectRom & selectRom) {
+    this->selectRom = selectRom;
+  }
+
+  /// @brief 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 with length 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeDataWithStop(uint_least8_t I2C_addr,
+                    Core::span<const uint_least8_t> data,
+                    uint_least8_t * wr_status = NULL);
+
+  /// @brief 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 with length 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeDataNoStop(uint_least8_t I2C_addr, Core::span<const uint_least8_t> data,
+                  uint_least8_t * wr_status = NULL);
+
+  /// @brief Write Data Only command.
+  /// @details Output on I2C: Write Data [1-255]
+  /// @param[in] data I2C data to write with length 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeDataOnly(Core::span<const uint_least8_t> data,
+                uint_least8_t * wr_status = NULL);
+
+  /// @brief Write Data Only With Stop command.
+  /// @details Output on I2C: Write Data [1-255], P
+  /// @param[in] data I2C data to write with length 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeDataOnlyWithStop(Core::span<const uint_least8_t> data,
+                        uint_least8_t * wr_status = NULL);
+
+  /// @brief 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 with length 1-255.
+  /// @param[out] read_data I2C data that was read with length 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.
+  MaximInterfaceDevices_EXPORT Core::error_code writeReadDataWithStop(
+      uint_least8_t I2C_addr, Core::span<const uint_least8_t> write_data,
+      Core::span<uint_least8_t> read_data, uint_least8_t * wr_status = NULL);
+
+  /// @brief 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 with length 1-255.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readDataWithStop(uint_least8_t I2C_addr, Core::span<uint_least8_t> data);
+
+  /// Write to Configuration Register of DS28E17.
+  MaximInterfaceDevices_EXPORT Core::error_code writeConfigReg(I2CSpeed speed);
+
+  /// @brief Read the Configuration Register of DS28E17.
+  /// @param[out] speed Speed read from configuration register.
+  MaximInterfaceDevices_EXPORT Core::error_code readConfigReg(I2CSpeed & speed);
+
+  /// @brief Put 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.
+  MaximInterfaceDevices_EXPORT Core::error_code enableSleepMode();
+
+  /// @brief 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.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readDeviceRevision(uint_least8_t & rev);
+
+  MaximInterfaceDevices_EXPORT static const Core::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
+  };
+
+  Core::error_code sendPacket(Command command, const uint_least8_t * I2C_addr,
+                              Core::span<const uint_least8_t> write_data,
+                              Core::span<uint_least8_t> read_data,
+                              uint_least8_t * wr_status);
+
+  Core::SelectRom selectRom;
+  Core::OneWireMaster * master;
+};
+
+inline Core::error_code make_error_code(DS28E17::ErrorValue e) {
+  return Core::error_code(e, DS28E17::errorCategory());
+}
+
+} // namespace MaximInterfaceDevices
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS28E38.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,302 @@
+/*******************************************************************************
+* 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 <algorithm>
+#include <MaximInterfaceCore/Error.hpp>
+#include "DS28E38.hpp"
+
+namespace MaximInterfaceDevices {
+
+using namespace Core;
+using std::copy;
+
+static const int readMemoryTimeMs = 30;
+static const int writeMemoryTimeMs = 65;
+static const int writeStateTimeMs = 15;
+static const int generateEccKeyPairTimeMs = 200;
+static const int generateEcdsaSignatureTimeMs = 130;
+static const int trngOnDemandCheckTimeMs = 20;
+static const int trngGenerationTimeMs = 10;
+
+const int DS28E38::decrementCounterPage;
+const int DS28E38::publicKeyXPage;
+const int DS28E38::publicKeyYPage;
+const int DS28E38::privateKeyPage;
+const int DS28E38::memoryPages;
+
+error_code DS28E38::writeMemory(int pageNum, Page::const_span page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t request[2 + Page::size];
+  request[0] = 0x96;
+  request[1] = pageNum;
+  copy(page.begin(), page.end(), request + 2);
+  return runCommand(request, writeMemoryTimeMs);
+}
+
+error_code DS28E38::readMemory(int pageNum, Page::span page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[1 + Page::size];
+  buffer[0] = 0x44;
+  buffer[1] = pageNum;
+  span<uint_least8_t> response(buffer);
+  const error_code result =
+      runCommand(make_span(buffer, 2), readMemoryTimeMs, response);
+  if (!result) {
+    copy(response.begin(), response.end(), page.begin());
+  }
+  return result;
+}
+
+error_code DS28E38::readStatus(bool entropyHealthTest, Status & status) {
+  int delay = readMemoryTimeMs;
+  if (entropyHealthTest) {
+    delay += trngOnDemandCheckTimeMs;
+  }
+  uint_least8_t buffer[Status::PageProtectionList::csize + ManId::size +
+                       Status::RomVersion::csize + 2];
+  buffer[0] = 0xAA;
+  buffer[1] = entropyHealthTest ? 0x01 : 0x00;
+  span<uint_least8_t> response(buffer);
+  error_code result = runCommand(make_span(buffer, 2), delay, response);
+  if (!result) {
+    span<uint_least8_t>::const_iterator responseIt = response.begin();
+    for (Status::PageProtectionList::iterator it =
+             status.pageProtection.begin();
+         it != status.pageProtection.end(); ++it) {
+      *it = *responseIt;
+      ++responseIt;
+    }
+    span<uint_least8_t>::const_iterator responseItEnd =
+        responseIt + status.manId.size();
+    copy(responseIt, responseItEnd, status.manId.begin());
+    responseIt = responseItEnd;
+    responseItEnd = responseIt + status.romVersion.size();
+    copy(responseIt, responseItEnd, status.romVersion.begin());
+    responseIt = responseItEnd;
+    switch (*responseIt) {
+    case Status::TestNotPerformed:
+    case Status::EntropyHealthy:
+    case Status::EntropyNotHealthy:
+      status.entropyHealthTestStatus =
+          static_cast<Status::EntropyHealthTestStatus>(*responseIt);
+      break;
+
+    default:
+      result = make_error_code(InvalidResponseError);
+      break;
+    }
+  }
+  return result;
+}
+
+error_code DS28E38::setPageProtection(int pageNum,
+                                      const PageProtection & protection) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  int delay = writeStateTimeMs;
+  if (pageNum == decrementCounterPage) {
+    delay += writeMemoryTimeMs;
+  }
+  const uint_least8_t request[] = {
+      0xC3, static_cast<uint_least8_t>(pageNum),
+      static_cast<uint_least8_t>(protection.to_ulong())};
+  return runCommand(request, delay);
+}
+
+error_code
+DS28E38::computeAndReadPageAuthentication(int pageNum, bool anonymous,
+                                          Page::const_span challenge,
+                                          Ecc256::Signature::span signature) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const size_t requestSize = 2 + Page::size;
+  const size_t responseSize = 1 + 2 * Ecc256::Scalar::size;
+  uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
+  buffer[0] = 0xA5;
+  buffer[1] = pageNum | (anonymous ? 0xE0 : 0x00);
+  copy(challenge.begin(), challenge.end(), buffer + 2);
+  span<uint_least8_t> response(buffer, responseSize);
+  const error_code result = runCommand(make_span(buffer, requestSize),
+                                       generateEcdsaSignatureTimeMs, response);
+  if (!result) {
+    span<uint_least8_t>::const_iterator begin = response.begin();
+    span<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 DS28E38::decrementCounter() {
+  const uint_least8_t request = 0xC9;
+  return runCommand(make_span(&request, 1), writeMemoryTimeMs);
+}
+
+error_code DS28E38::disableDevice() {
+  const uint_least8_t request[] = {0x33, 0x9E, 0xA7, 0x49, 0xFB,
+                                   0x10, 0x62, 0x0A, 0x26};
+  return runCommand(request, writeStateTimeMs);
+}
+
+error_code DS28E38::generateEcc256KeyPair(bool privateKeyPuf,
+                                          bool writeProtectEnable) {
+  int delay = generateEccKeyPairTimeMs;
+  if (writeProtectEnable) {
+    delay += writeStateTimeMs;
+  }
+  uint_least8_t request[] = {0xCB, 0x00};
+  if (privateKeyPuf) {
+    request[1] |= 0x01;
+  }
+  if (writeProtectEnable) {
+    request[1] |= 0x80;
+  }
+  return runCommand(request, delay);
+}
+
+error_code DS28E38::readRng(span<uint_least8_t> data) {
+  const span<uint_least8_t>::index_type maxDataSize = 64;
+  if ((data.size() < 1) || (data.size() > maxDataSize)) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[1 + maxDataSize];
+  buffer[0] = 0xD2;
+  buffer[1] = static_cast<uint_least8_t>(data.size() - 1);
+  span<uint_least8_t> response(buffer, 1 + data.size());
+  const error_code result =
+      runCommand(make_span(buffer, 2), trngGenerationTimeMs, response);
+  if (!result) {
+    copy(response.begin(), response.end(), data.begin());
+  }
+  return result;
+}
+
+error_code DS28E38::runCommand(span<const uint_least8_t> request, int delayTime,
+                               span<uint_least8_t> & response) {
+  const span<const uint_least8_t>::index_type responseInputSize =
+      response.size();
+  error_code result = doRunCommand(request, delayTime, response);
+  if (result) {
+    return result;
+  }
+  if (response.empty()) {
+    return make_error_code(InvalidResponseError);
+  }
+  // Parse command result byte.
+  switch (response[0]) {
+  case 0xAA:
+    // Success response.
+    if (response.size() != responseInputSize) {
+      result = make_error_code(InvalidResponseError);
+    }
+    break;
+
+  case 0x00:
+    result = make_error_code(InvalidResponseError);
+    break;
+
+  default:
+    result.assign(response[0], errorCategory());
+    break;
+  }
+  response = response.subspan(1);
+  return result;
+}
+
+error_code DS28E38::runCommand(span<const uint_least8_t> request,
+                               int delayTime) {
+  uint_least8_t buffer;
+  span<uint_least8_t> response(&buffer, 1);
+  return runCommand(request, delayTime, response);
+}
+
+const error_category & DS28E38::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "DS28E38"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case InvalidOperationError:
+        return "Invalid Operation Error";
+
+      case InvalidParameterError:
+        return "Invalid Parameter Error";
+
+      case InvalidSequenceError:
+        return "Invalid Sequence Error";
+
+      case InternalError:
+        return "Internal Error";
+
+      case DeviceDisabledError:
+        return "Device Disabled Error";
+
+      case InvalidResponseError:
+        return "Invalid Response Error";
+      }
+      return defaultErrorMessage(condition);
+    }
+  } instance;
+  return instance;
+}
+
+error_code readManId(DS28E38 & ds28e38, ManId::span manId) {
+  DS28E38::Status status;
+  const error_code result = ds28e38.readStatus(false, status);
+  if (!result) {
+    copy(make_span(status.manId), manId);
+  }
+  return result;
+}
+
+DS28E38::PageAuthenticationData &
+DS28E38::PageAuthenticationData::setAnonymousRomId() {
+  std::fill(romId().begin(), romId().end(), 0xFF);
+  return *this;
+}
+
+} // namespace MaximInterfaceDevices
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS28E38.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,323 @@
+/*******************************************************************************
+* 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 MaximInterfaceDevices_DS28E38
+#define MaximInterfaceDevices_DS28E38
+
+#include <stdint.h>
+#include <MaximInterfaceCore/Algorithm.hpp>
+#include <MaximInterfaceCore/array_span.hpp>
+#include <MaximInterfaceCore/Ecc256.hpp>
+#include <MaximInterfaceCore/FlagSet.hpp>
+#include <MaximInterfaceCore/ManId.hpp>
+#include <MaximInterfaceCore/RomId.hpp>
+#include <MaximInterfaceCore/RunCommand.hpp>
+#include <MaximInterfaceCore/system_error.hpp>
+#include "Config.hpp"
+
+namespace MaximInterfaceDevices {
+
+class DS28E38 {
+public:
+  /// Device command results.
+  enum ErrorValue {
+    InvalidOperationError = 0x55,
+    InvalidParameterError = 0x77,
+    InvalidSequenceError = 0x33,
+    InternalError = 0x22,
+    DeviceDisabledError = 0x88,
+    InvalidResponseError =
+        0x100 ///< Command response does not match expected format.
+  };
+
+  /// @name Device memory pages
+  /// @{
+
+  static const int decrementCounterPage = 3;
+  static const int publicKeyXPage = 4;
+  static const int publicKeyYPage = 5;
+  static const int privateKeyPage = 6;
+
+  /// @}
+
+  static const int memoryPages = 7;
+
+  /// Holds a device memory page.
+  typedef Core::array_span<uint_least8_t, 32> Page;
+
+  // Format page authentication input data.
+  class PageAuthenticationData;
+
+  /// Page protection types.
+  enum PageProtectionType {
+    RP = 0x01, ///< Read protection.
+    WP = 0x02, ///< Write protection.
+    EM = 0x04, ///< EPROM emulation mode.
+    DC = 0x08, ///< Decrement counter.
+    PF = 0x10  ///< PUF used as private key.
+  };
+  typedef Core::FlagSet<PageProtectionType, 5> PageProtection;
+
+  struct Status {
+    enum EntropyHealthTestStatus {
+      TestNotPerformed = 0xFF,
+      EntropyHealthy = 0xAA,
+      EntropyNotHealthy = 0xDD
+    };
+
+    typedef Core::array<PageProtection, memoryPages> PageProtectionList;
+    typedef Core::array<uint_least8_t, 2> RomVersion;
+
+    PageProtectionList pageProtection;
+    Core::ManId::array manId;
+    RomVersion romVersion;
+    EntropyHealthTestStatus entropyHealthTestStatus;
+  };
+
+  explicit DS28E38(const Core::RunCommand & runCommand)
+      : doRunCommand(runCommand) {}
+
+  void setRunCommand(const Core::RunCommand & runCommand) {
+    doRunCommand = runCommand;
+  }
+
+  /// @brief Write memory with no protection.
+  /// @param pageNum Number of page to write.
+  /// @param page Data to write.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeMemory(int pageNum, Page::const_span page);
+
+  /// @brief Read memory with no protection.
+  /// @param pageNum Number of page to read.
+  /// @param[out] page Data that was read.
+  MaximInterfaceDevices_EXPORT Core::error_code readMemory(int pageNum,
+                                                           Page::span page);
+
+  /// @brief
+  /// Reads the current status of the device and optionally performs an
+  /// entropy health test.
+  /// @param entropyHealthTest True to perform an entropy health test.
+  /// @param[out] status Status that was read.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readStatus(bool entropyHealthTest, Status & status);
+
+  /// @brief Set the protection settings of a page.
+  /// @param pageNum Number of page to write.
+  /// @param protection Protection to write.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  setPageProtection(int pageNum, const PageProtection & protection);
+
+  /// @brief Compute and read page authentication with ECDSA.
+  /// @param pageNum Number of page to authenticate.
+  /// @param anonymous True to disable use of ROM ID in computation.
+  /// @param challenge Random challenge used to prevent replay attacks.
+  /// @param[out] signature Computed page signature.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeAndReadPageAuthentication(int pageNum, bool anonymous,
+                                   Page::const_span challenge,
+                                   Core::Ecc256::Signature::span signature);
+
+  /// Decrement the decrement-only counter.
+  MaximInterfaceDevices_EXPORT Core::error_code decrementCounter();
+
+  /// Permanently disable the device.
+  MaximInterfaceDevices_EXPORT Core::error_code disableDevice();
+
+  /// @brief Generate a new ECDSA public key from an existing private key.
+  /// @param privateKeyPuf True if PUF is used as the private key.
+  /// @param writeProtectEnable True to lock the key against further writes.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  generateEcc256KeyPair(bool privateKeyPuf, bool writeProtectEnable);
+
+  /// @brief Read a block of random data from the RNG.
+  /// @param[out] data Random data from RNG with length from 1 to 64.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readRng(Core::span<uint_least8_t> data);
+
+  MaximInterfaceDevices_EXPORT static const Core::error_category &
+  errorCategory();
+
+protected:
+  MaximInterfaceDevices_EXPORT Core::error_code
+  runCommand(Core::span<const uint_least8_t> request, int delayTime,
+             Core::span<uint_least8_t> & response);
+
+  MaximInterfaceDevices_EXPORT Core::error_code
+  runCommand(Core::span<const uint_least8_t> request, int delayTime);
+
+private:
+  Core::RunCommand doRunCommand;
+};
+
+inline Core::error_code make_error_code(DS28E38::ErrorValue e) {
+  return Core::error_code(e, DS28E38::errorCategory());
+}
+
+/// @brief Read the device MAN ID using the Read Status command.
+/// @param ds28e38 Device to read.
+/// @param[out] manId Read MAN ID valid when operation is successful.
+MaximInterfaceDevices_EXPORT Core::error_code
+readManId(DS28E38 & ds28e38, Core::ManId::span manId);
+
+/// Format page authentication input data.
+class DS28E38::PageAuthenticationData {
+public:
+  typedef Core::array_span<uint_least8_t, Core::RomId::size + 2 * Page::size +
+                                              1 + Core::ManId::size>
+      Result;
+
+  PageAuthenticationData() : result_() {}
+
+  /// Formatted data result.
+  Result::const_span result() const { return result_; }
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() {
+    return make_span(result_).subspan<romIdIdx, Core::RomId::size>();
+  }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const {
+    return const_cast<PageAuthenticationData &>(*this).romId();
+  }
+
+  /// Set ROM ID.
+  PageAuthenticationData & setRomId(Core::RomId::const_span romId) {
+    copy(romId, this->romId());
+    return *this;
+  }
+
+  /// Set ROM ID for use in anonymous mode.
+  MaximInterfaceDevices_EXPORT PageAuthenticationData & setAnonymousRomId();
+
+  /// @}
+
+  /// @name Page
+  /// @brief Data from a device memory page.
+  /// @{
+
+  /// Get mutable page.
+  Page::span page() {
+    return make_span(result_).subspan<pageIdx, Page::size>();
+  }
+
+  /// Get immutable page.
+  Page::const_span page() const {
+    return const_cast<PageAuthenticationData &>(*this).page();
+  }
+
+  /// Set page.
+  PageAuthenticationData & setPage(Page::const_span page) {
+    copy(page, this->page());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Challenge
+  /// @brief Random challenge used to prevent replay attacks.
+  /// @{
+
+  /// Get mutable Challenge.
+  Page::span challenge() {
+    return make_span(result_).subspan<challengeIdx, Page::size>();
+  }
+
+  /// Get immutable Challenge.
+  Page::const_span challenge() const {
+    return const_cast<PageAuthenticationData &>(*this).challenge();
+  }
+
+  /// Set Challenge.
+  PageAuthenticationData & setChallenge(Page::const_span challenge) {
+    copy(challenge, this->challenge());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Number of the page to use data from.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return result_[pageNumIdx]; }
+
+  /// Set page number.
+  PageAuthenticationData & setPageNum(int pageNum) {
+    result_[pageNumIdx] = pageNum;
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() {
+    return make_span(result_).subspan<manIdIdx, Core::ManId::size>();
+  }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const {
+    return const_cast<PageAuthenticationData &>(*this).manId();
+  }
+
+  /// Set MAN ID.
+  PageAuthenticationData & setManId(Core::ManId::const_span manId) {
+    copy(manId, this->manId());
+    return *this;
+  }
+
+  /// @}
+
+private:
+  typedef Result::span::index_type index;
+
+  static const index romIdIdx = 0;
+  static const index pageIdx = romIdIdx + Core::RomId::size;
+  static const index challengeIdx = pageIdx + Page::size;
+  static const index pageNumIdx = challengeIdx + Page::size;
+  static const index manIdIdx = pageNumIdx + 1;
+
+  Result::array result_;
+};
+
+} // namespace MaximInterfaceDevices
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS28E39.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,346 @@
+/*******************************************************************************
+* Copyright (C) 2018 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 <algorithm>
+#include <MaximInterfaceCore/Error.hpp>
+#include "DS28E39.hpp"
+
+namespace MaximInterfaceDevices {
+
+using namespace Core;
+using std::copy;
+
+static const int readMemoryTimeMs = 30;
+static const int writeMemoryTimeMs = 65;
+static const int writeStateTimeMs = 15;
+static const int generateEccKeyPairTimeMs = 200;
+static const int generateEcdsaSignatureTimeMs = 130;
+static const int trngOnDemandCheckTimeMs = 20;
+static const int trngGenerationTimeMs = 10;
+static const int verifyEcdsaSignatureTimeMs = 180;
+
+const int DS28E39::decrementCounterPage;
+const int DS28E39::authorityPublicKeyXPage;
+const int DS28E39::authorityPublicKeyYPage;
+const int DS28E39::writePublicKeyXPage;
+const int DS28E39::writePublicKeyYPage;
+const int DS28E39::memoryPages;
+
+error_code DS28E39::writeMemory(int pageNum, Page::const_span page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t request[2 + Page::size];
+  request[0] = 0x96;
+  request[1] = pageNum;
+  copy(page.begin(), page.end(), request + 2);
+  return runCommand(request, writeMemoryTimeMs);
+}
+
+error_code DS28E39::readMemory(int pageNum, Page::span page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[1 + Page::size];
+  buffer[0] = 0x44;
+  buffer[1] = pageNum;
+  span<uint_least8_t> response(buffer);
+  const error_code result =
+      runCommand(make_span(buffer, 2), readMemoryTimeMs, response);
+  if (!result) {
+    copy(response.begin(), response.end(), page.begin());
+  }
+  return result;
+}
+
+error_code DS28E39::readStatus(bool entropyHealthTest, Status & status) {
+  int delay = readMemoryTimeMs;
+  if (entropyHealthTest) {
+    delay += trngOnDemandCheckTimeMs;
+  }
+  uint_least8_t buffer[Status::PageProtectionList::csize + ManId::size +
+                       Status::RomVersion::csize + 2];
+  buffer[0] = 0xAA;
+  buffer[1] = entropyHealthTest ? 0x01 : 0x00;
+  span<uint_least8_t> response(buffer);
+  error_code result = runCommand(make_span(buffer, 2), delay, response);
+  if (!result) {
+    span<uint_least8_t>::const_iterator responseIt = response.begin();
+    for (Status::PageProtectionList::iterator it =
+             status.pageProtection.begin();
+         it != status.pageProtection.end(); ++it) {
+      *it = *responseIt;
+      ++responseIt;
+    }
+    span<uint_least8_t>::const_iterator responseItEnd =
+        responseIt + status.manId.size();
+    copy(responseIt, responseItEnd, status.manId.begin());
+    responseIt = responseItEnd;
+    responseItEnd = responseIt + status.romVersion.size();
+    copy(responseIt, responseItEnd, status.romVersion.begin());
+    responseIt = responseItEnd;
+    switch (*responseIt) {
+    case Status::TestNotPerformed:
+    case Status::EntropyHealthy:
+    case Status::EntropyNotHealthy:
+      status.entropyHealthTestStatus =
+          static_cast<Status::EntropyHealthTestStatus>(*responseIt);
+      break;
+
+    default:
+      result = make_error_code(InvalidResponseError);
+      break;
+    }
+  }
+  return result;
+}
+
+error_code DS28E39::setPageProtection(int pageNum,
+                                      const PageProtection & protection) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  int delay = writeStateTimeMs;
+  if (pageNum == decrementCounterPage) {
+    delay += writeMemoryTimeMs;
+  }
+  const uint_least8_t request[] = {
+      0xC3, static_cast<uint_least8_t>(pageNum),
+      static_cast<uint_least8_t>(protection.to_ulong())};
+  return runCommand(request, delay);
+}
+
+error_code
+DS28E39::computeAndReadPageAuthentication(int pageNum, bool anonymous,
+                                          Page::const_span challenge,
+                                          Ecc256::Signature::span signature) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const size_t requestSize = 2 + Page::size;
+  const size_t responseSize = 1 + 2 * Ecc256::Scalar::size;
+  uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
+  buffer[0] = 0xA5;
+  buffer[1] = pageNum | (anonymous ? 0xE0 : 0x00);
+  copy(challenge.begin(), challenge.end(), buffer + 2);
+  span<uint_least8_t> response(buffer, responseSize);
+  const error_code result = runCommand(make_span(buffer, requestSize),
+                                       generateEcdsaSignatureTimeMs, response);
+  if (!result) {
+    span<uint_least8_t>::const_iterator begin = response.begin();
+    span<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 DS28E39::decrementCounter() {
+  const uint_least8_t request = 0xC9;
+  return runCommand(make_span(&request, 1), writeMemoryTimeMs);
+}
+
+error_code DS28E39::disableDevice() {
+  const uint_least8_t request[] = {0x33, 0x9E, 0xA7, 0x49, 0xFB,
+                                   0x10, 0x62, 0x0A, 0x26};
+  return runCommand(request, writeStateTimeMs);
+}
+
+error_code
+DS28E39::readDevicePublicKey(Ecc256::PublicKey::span devicePublicKey) {
+  uint_least8_t buffer[1 + 2 * Ecc256::Scalar::size];
+  buffer[0] = 0xCB;
+  span<uint_least8_t> response(buffer);
+  const error_code result =
+      runCommand(make_span(buffer, 1), generateEccKeyPairTimeMs, response);
+  if (!result) {
+    span<uint_least8_t>::const_iterator begin = response.begin();
+    span<uint_least8_t>::const_iterator end = begin + devicePublicKey.x.size();
+    copy(begin, end, devicePublicKey.x.begin());
+    begin = end;
+    end = begin + devicePublicKey.y.size();
+    copy(begin, end, devicePublicKey.y.begin());
+  }
+  return result;
+}
+
+error_code DS28E39::readRng(span<uint_least8_t> data) {
+  const span<uint_least8_t>::index_type maxDataSize = 64;
+  if ((data.size() < 1) || (data.size() > maxDataSize)) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[1 + maxDataSize];
+  buffer[0] = 0xD2;
+  buffer[1] = static_cast<uint_least8_t>(data.size() - 1);
+  span<uint_least8_t> response(buffer, 1 + data.size());
+  const error_code result =
+      runCommand(make_span(buffer, 2), trngGenerationTimeMs, response);
+  if (!result) {
+    copy(response.begin(), response.end(), data.begin());
+  }
+  return result;
+}
+
+error_code
+DS28E39::authenticatePublicKey(Ecc256::Signature::const_span certificate,
+                               span<const uint_least8_t> customization) {
+  static const span<const uint_least8_t>::index_type maxCustomizationSize = 32;
+  static const span<const uint_least8_t>::index_type signatureSize =
+      2 * Ecc256::Scalar::size;
+
+  if (customization.size() < 1 || customization.size() > maxCustomizationSize) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t request[1 + signatureSize + maxCustomizationSize];
+  uint_least8_t * requestIt = request;
+  *requestIt++ = 0x59;
+  requestIt = copy(certificate.r.begin(), certificate.r.end(), requestIt);
+  requestIt = copy(certificate.s.begin(), certificate.s.end(), requestIt);
+  requestIt = copy(customization.begin(), customization.end(), requestIt);
+  return runCommand(make_span(request, requestIt), verifyEcdsaSignatureTimeMs);
+}
+
+error_code
+DS28E39::authenticatedWriteMemory(int pageNum, Page::const_span page,
+                                  Ecc256::Signature::const_span signature) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t request[2 + Page::size + 2 * Ecc256::Scalar::size];
+  uint_least8_t * requestIt = request;
+  *requestIt++ = 0x89;
+  *requestIt++ = pageNum;
+  requestIt = copy(page.begin(), page.end(), requestIt);
+  requestIt = copy(signature.r.begin(), signature.r.end(), requestIt);
+  copy(signature.s.begin(), signature.s.end(), requestIt);
+  return runCommand(request, verifyEcdsaSignatureTimeMs + writeMemoryTimeMs);
+}
+
+error_code DS28E39::runCommand(span<const uint_least8_t> request, int delayTime,
+                               span<uint_least8_t> & response) {
+  const span<const uint_least8_t>::index_type responseInputSize =
+      response.size();
+  error_code result = doRunCommand(request, delayTime, response);
+  if (result) {
+    return result;
+  }
+  if (response.empty()) {
+    return make_error_code(InvalidResponseError);
+  }
+  // Parse command result byte.
+  switch (response[0]) {
+  case 0xAA:
+    // Success response.
+    if (response.size() != responseInputSize) {
+      result = make_error_code(InvalidResponseError);
+    }
+    break;
+
+  case 0x00:
+    result = make_error_code(AuthenticationError);
+    break;
+
+  default:
+    result.assign(response[0], errorCategory());
+    break;
+  }
+  response = response.subspan(1);
+  return result;
+}
+
+error_code DS28E39::runCommand(span<const uint_least8_t> request,
+                               int delayTime) {
+  uint_least8_t buffer;
+  span<uint_least8_t> response(&buffer, 1);
+  return runCommand(request, delayTime, response);
+}
+
+const error_category & DS28E39::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "DS28E39"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case InvalidOperationError:
+        return "Invalid Operation Error";
+
+      case InvalidParameterError:
+        return "Invalid Parameter Error";
+
+      case InvalidSequenceError:
+        return "Invalid Sequence Error";
+
+      case InternalError:
+        return "Internal Error";
+
+      case DeviceDisabledError:
+        return "Device Disabled Error";
+
+      case AuthenticationError:
+        return "Authentication Error";
+
+      case InvalidResponseError:
+        return "Invalid Response Error";
+      }
+      return defaultErrorMessage(condition);
+    }
+  } instance;
+  return instance;
+}
+
+error_code readManId(DS28E39 & ds28e39, ManId::span manId) {
+  DS28E39::Status status;
+  const error_code result = ds28e39.readStatus(false, status);
+  if (!result) {
+    copy(make_span(status.manId), manId);
+  }
+  return result;
+}
+
+DS28E39::PageAuthenticationData &
+DS28E39::PageAuthenticationData::setAnonymousRomId() {
+  std::fill(romId().begin(), romId().end(), 0xFF);
+  return *this;
+}
+
+} // namespace MaximInterfaceDevices
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS28E39.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,446 @@
+/*******************************************************************************
+* Copyright (C) 2018 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 MaximInterfaceDevices_DS28E39
+#define MaximInterfaceDevices_DS28E39
+
+#include <stdint.h>
+#include <MaximInterfaceCore/Algorithm.hpp>
+#include <MaximInterfaceCore/array_span.hpp>
+#include <MaximInterfaceCore/Ecc256.hpp>
+#include <MaximInterfaceCore/FlagSet.hpp>
+#include <MaximInterfaceCore/ManId.hpp>
+#include <MaximInterfaceCore/RomId.hpp>
+#include <MaximInterfaceCore/RunCommand.hpp>
+#include <MaximInterfaceCore/system_error.hpp>
+#include "Config.hpp"
+
+namespace MaximInterfaceDevices {
+
+class DS28E39 {
+public:
+  /// Device command results.
+  enum ErrorValue {
+    InvalidOperationError = 0x55,
+    InvalidParameterError = 0x77,
+    InvalidSequenceError = 0x33,
+    InternalError = 0x22,
+    DeviceDisabledError = 0x88,
+    AuthenticationError = 0x100,
+    InvalidResponseError ///< Command response does not match expected format.
+  };
+
+  /// @name Device memory pages
+  /// @{
+
+  static const int decrementCounterPage = 4;
+  static const int authorityPublicKeyXPage = 5;
+  static const int authorityPublicKeyYPage = 6;
+  static const int writePublicKeyXPage = 7;
+  static const int writePublicKeyYPage = 8;
+
+  /// @}
+
+  static const int memoryPages = 9;
+
+  /// Holds a device memory page.
+  typedef Core::array_span<uint_least8_t, 32> Page;
+
+  // Format page authentication input data.
+  class PageAuthenticationData;
+
+  // Format authenticated write input data.
+  class WriteAuthenticationData;
+
+  /// Page protection types.
+  enum PageProtectionType {
+    RP = 0x01, ///< Read protection.
+    WP = 0x02, ///< Write protection.
+    EM = 0x04, ///< EPROM emulation mode.
+    DC = 0x08, ///< Decrement counter.
+    ECW = 0x10 ///< Authenticated write.
+  };
+  typedef Core::FlagSet<PageProtectionType, 5> PageProtection;
+
+  struct Status {
+    enum EntropyHealthTestStatus {
+      TestNotPerformed = 0xFF,
+      EntropyHealthy = 0xAA,
+      EntropyNotHealthy = 0xDD
+    };
+
+    typedef Core::array<PageProtection, memoryPages - 2> PageProtectionList;
+    typedef Core::array<uint_least8_t, 2> RomVersion;
+
+    PageProtectionList pageProtection;
+    Core::ManId::array manId;
+    RomVersion romVersion;
+    EntropyHealthTestStatus entropyHealthTestStatus;
+  };
+
+  explicit DS28E39(const Core::RunCommand & runCommand)
+      : doRunCommand(runCommand) {}
+
+  void setRunCommand(const Core::RunCommand & runCommand) {
+    doRunCommand = runCommand;
+  }
+
+  /// @brief Write memory with no protection.
+  /// @param pageNum Number of page to write.
+  /// @param page Data to write.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeMemory(int pageNum, Page::const_span page);
+
+  /// @brief Read memory with no protection.
+  /// @param pageNum Number of page to read.
+  /// @param[out] page Data that was read.
+  MaximInterfaceDevices_EXPORT Core::error_code readMemory(int pageNum,
+                                                           Page::span page);
+
+  /// @brief
+  /// Reads the current status of the device and optionally performs an
+  /// entropy health test.
+  /// @param entropyHealthTest True to perform an entropy health test.
+  /// @param[out] status Status that was read.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readStatus(bool entropyHealthTest, Status & status);
+
+  /// @brief Set the protection settings of a page.
+  /// @param pageNum Number of page to write.
+  /// @param protection Protection to write.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  setPageProtection(int pageNum, const PageProtection & protection);
+
+  /// @brief Compute and read page authentication with ECDSA.
+  /// @param pageNum Number of page to authenticate.
+  /// @param anonymous True to disable use of ROM ID in computation.
+  /// @param challenge Random challenge used to prevent replay attacks.
+  /// @param[out] signature Computed page signature.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeAndReadPageAuthentication(int pageNum, bool anonymous,
+                                   Page::const_span challenge,
+                                   Core::Ecc256::Signature::span signature);
+
+  /// Decrement the decrement-only counter.
+  MaximInterfaceDevices_EXPORT Core::error_code decrementCounter();
+
+  /// Permanently disable the device.
+  MaximInterfaceDevices_EXPORT Core::error_code disableDevice();
+
+  /// @brief Generate the device's ECDSA public key from the PUF private key.
+  /// @param[out] devicePublicKey Device Public Key
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readDevicePublicKey(Core::Ecc256::PublicKey::span devicePublicKey);
+
+  /// @brief Read a block of random data from the RNG.
+  /// @param[out] data Random data from RNG with length from 1 to 64.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readRng(Core::span<uint_least8_t> data);
+
+  /// @brief
+  /// Authenticate a public key for authenticated writes using the
+  /// Authority Public Key.
+  /// @param certificate
+  /// Certificate to use for authentication of the Write Public Key.
+  /// @param customization
+  /// Certificate customization with length from 1 to 32.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  authenticatePublicKey(Core::Ecc256::Signature::const_span certificate,
+                        Core::span<const uint_least8_t> customization);
+
+  /// @brief Write with ECDSA authentication using the Write Public Key.
+  /// @param pageNum Number of page to write.
+  /// @param page Data to write.
+  /// @param signature Signature to use for authentication of page data.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  authenticatedWriteMemory(int pageNum, Page::const_span page,
+                           Core::Ecc256::Signature::const_span signature);
+
+  MaximInterfaceDevices_EXPORT static const Core::error_category &
+  errorCategory();
+
+protected:
+  MaximInterfaceDevices_EXPORT Core::error_code
+  runCommand(Core::span<const uint_least8_t> request, int delayTime,
+             Core::span<uint_least8_t> & response);
+
+  MaximInterfaceDevices_EXPORT Core::error_code
+  runCommand(Core::span<const uint_least8_t> request, int delayTime);
+
+private:
+  Core::RunCommand doRunCommand;
+};
+
+inline Core::error_code make_error_code(DS28E39::ErrorValue e) {
+  return Core::error_code(e, DS28E39::errorCategory());
+}
+
+/// @brief Read the device MAN ID using the Read Status command.
+/// @param ds28e39 Device to read.
+/// @param[out] manId Read MAN ID valid when operation is successful.
+MaximInterfaceDevices_EXPORT Core::error_code
+readManId(DS28E39 & ds28e39, Core::ManId::span manId);
+
+/// Format page authentication input data.
+class DS28E39::PageAuthenticationData {
+public:
+  typedef Core::array_span<uint_least8_t, Core::RomId::size + 2 * Page::size +
+                                              1 + Core::ManId::size>
+      Result;
+
+  PageAuthenticationData() : result_() {}
+
+  /// Formatted data result.
+  Result::const_span result() const { return result_; }
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() {
+    return make_span(result_).subspan<romIdIdx, Core::RomId::size>();
+  }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const {
+    return const_cast<PageAuthenticationData &>(*this).romId();
+  }
+
+  /// Set ROM ID.
+  PageAuthenticationData & setRomId(Core::RomId::const_span romId) {
+    copy(romId, this->romId());
+    return *this;
+  }
+
+  /// Set ROM ID for use in anonymous mode.
+  MaximInterfaceDevices_EXPORT PageAuthenticationData & setAnonymousRomId();
+
+  /// @}
+
+  /// @name Page
+  /// @brief Data from a device memory page.
+  /// @{
+
+  /// Get mutable page.
+  Page::span page() {
+    return make_span(result_).subspan<pageIdx, Page::size>();
+  }
+
+  /// Get immutable page.
+  Page::const_span page() const {
+    return const_cast<PageAuthenticationData &>(*this).page();
+  }
+
+  /// Set page.
+  PageAuthenticationData & setPage(Page::const_span page) {
+    copy(page, this->page());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Challenge
+  /// @brief Random challenge used to prevent replay attacks.
+  /// @{
+
+  /// Get mutable Challenge.
+  Page::span challenge() {
+    return make_span(result_).subspan<challengeIdx, Page::size>();
+  }
+
+  /// Get immutable Challenge.
+  Page::const_span challenge() const {
+    return const_cast<PageAuthenticationData &>(*this).challenge();
+  }
+
+  /// Set Challenge.
+  PageAuthenticationData & setChallenge(Page::const_span challenge) {
+    copy(challenge, this->challenge());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Number of the page to use data from.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return result_[pageNumIdx]; }
+
+  /// Set page number.
+  PageAuthenticationData & setPageNum(int pageNum) {
+    result_[pageNumIdx] = pageNum;
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() {
+    return make_span(result_).subspan<manIdIdx, Core::ManId::size>();
+  }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const {
+    return const_cast<PageAuthenticationData &>(*this).manId();
+  }
+
+  /// Set MAN ID.
+  PageAuthenticationData & setManId(Core::ManId::const_span manId) {
+    copy(manId, this->manId());
+    return *this;
+  }
+
+  /// @}
+
+private:
+  typedef Result::span::index_type index;
+
+  static const index romIdIdx = 0;
+  static const index pageIdx = romIdIdx + Core::RomId::size;
+  static const index challengeIdx = pageIdx + Page::size;
+  static const index pageNumIdx = challengeIdx + Page::size;
+  static const index manIdIdx = pageNumIdx + 1;
+
+  Result::array result_;
+};
+
+/// Format authenticated write input data.
+class DS28E39::WriteAuthenticationData {
+public:
+  typedef PageAuthenticationData::Result Result;
+
+  WriteAuthenticationData() : data() { setPageNum(0); }
+
+  /// Formatted data result.
+  Result::const_span result() const { return data.result(); }
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() { return data.romId(); }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const { return data.romId(); }
+
+  /// Set ROM ID.
+  WriteAuthenticationData & setRomId(Core::RomId::const_span romId) {
+    data.setRomId(romId);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Old page
+  /// @brief Existing data contained in the page.
+  /// @{
+
+  /// Get mutable old page.
+  Page::span oldPage() { return data.page(); }
+
+  /// Get immutable old page.
+  Page::const_span oldPage() const { return data.page(); }
+
+  /// Set old page.
+  WriteAuthenticationData & setOldPage(Page::const_span oldPage) {
+    data.setPage(oldPage);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name New page
+  /// @brief New data to write to the page.
+  /// @{
+
+  /// Get mutable new page.
+  Page::span newPage() { return data.challenge(); }
+
+  /// Get immutable new page.
+  Page::const_span newPage() const { return data.challenge(); }
+
+  /// Set new page.
+  WriteAuthenticationData & setNewPage(Page::const_span newPage) {
+    data.setChallenge(newPage);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Page number for write operation.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return data.pageNum() & 0x7F; }
+
+  /// Set page number.
+  WriteAuthenticationData & setPageNum(int pageNum) {
+    data.setPageNum(pageNum | 0x80);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() { return data.manId(); }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const { return data.manId(); }
+
+  /// Set MAN ID.
+  WriteAuthenticationData & setManId(Core::ManId::const_span manId) {
+    data.setManId(manId);
+    return *this;
+  }
+
+  /// @}
+
+private:
+  PageAuthenticationData data;
+};
+
+} // namespace MaximInterfaceDevices
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS28E83_DS28E84.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,678 @@
+/*******************************************************************************
+* Copyright (C) 2018 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 <algorithm>
+#include <MaximInterfaceCore/Error.hpp>
+#include "DS28E83_DS28E84.hpp"
+
+namespace MaximInterfaceDevices {
+
+using namespace Core;
+using std::copy;
+
+static const int readMemoryTimeMs = 2;
+static const int writeMemoryTimeMs = 100;
+static const int writeStateTimeMs = 15;
+static const int generateEccKeyPairTimeMs = 350;
+static const int generateEcdsaSignatureTimeMs = 80;
+static const int computeTimeMs = 4;
+static const int verifyEcdsaTimeMs = 160;
+static const int trngGenerationTimeMs = 40;
+static const int trngOnDemandCheckTimeMs = 65;
+
+static const uint_least8_t computeAndReadPageAuthenticationCmd = 0xA5;
+static const uint_least8_t readRngCmd = 0xD2;
+
+static const int memoryPages =
+    MaximInterfaceCore_MAX(DS28E83::memoryPages, DS28E84::memoryPages);
+static const int protectionBlocks = MaximInterfaceCore_MAX(
+    DS28E83::protectionBlocks, DS28E84::protectionBlocks);
+
+const int DS28E83_DS28E84::publicKeyAxPage;
+const int DS28E83_DS28E84::publicKeyAyPage;
+const int DS28E83_DS28E84::publicKeyBxPage;
+const int DS28E83_DS28E84::publicKeyByPage;
+const int DS28E83_DS28E84::authorityPublicKeyAxPage;
+const int DS28E83_DS28E84::authorityPublicKeyAyPage;
+const int DS28E83_DS28E84::authorityPublicKeyBxPage;
+const int DS28E83_DS28E84::authorityPublicKeyByPage;
+const int DS28E83_DS28E84::privateKeyAPage;
+const int DS28E83_DS28E84::privateKeyBPage;
+const int DS28E83_DS28E84::secretAPage;
+const int DS28E83_DS28E84::secretBPage;
+const int DS28E83_DS28E84::romOptionsPage;
+const int DS28E83_DS28E84::gpioControlPage;
+const int DS28E83_DS28E84::publicKeySxPage;
+const int DS28E83_DS28E84::publicKeySyPage;
+
+const int DS28E83::memoryPages;
+const int DS28E83::protectionBlocks;
+
+const int DS28E84::publicKeySxBackupPage;
+const int DS28E84::publicKeySyBackupPage;
+const int DS28E84::decrementCounterPage;
+const int DS28E84::memoryPages;
+const int DS28E84::protectionBlocks;
+
+error_code DS28E83_DS28E84::writeMemory(int pageNum, Page::const_span page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t request[2 + Page::size];
+  request[0] = 0x96;
+  request[1] = pageNum;
+  copy(page.begin(), page.end(), request + 2);
+  return runCommand(request, writeMemoryTimeMs);
+}
+
+error_code DS28E83_DS28E84::readMemory(int pageNum, Page::span page) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[1 + Page::size];
+  buffer[0] = 0x44;
+  buffer[1] = pageNum;
+  span<uint_least8_t> response(buffer);
+  const error_code result =
+      runCommand(make_span(buffer, 2), readMemoryTimeMs, response);
+  if (!result) {
+    copy(response.begin(), response.end(), page.begin());
+  }
+  return result;
+}
+
+error_code DS28E83_DS28E84::encryptedReadMemory(
+    int pageNum, KeySecret secret,
+    EncryptionChallenge::span encryptionChallenge, Page::span encryptedPage) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const size_t requestSize = 3;
+  const size_t responseSize = 1 + EncryptionChallenge::size + Page::size;
+  uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
+  buffer[0] = 0x4B;
+  buffer[1] = pageNum;
+  buffer[2] = secret;
+  span<uint_least8_t> response(buffer, responseSize);
+  const error_code result =
+      runCommand(make_span(buffer, requestSize),
+                 readMemoryTimeMs + computeTimeMs, response);
+  if (!result) {
+    span<uint_least8_t>::const_iterator begin = response.begin();
+    span<uint_least8_t>::const_iterator end =
+        begin + encryptionChallenge.size();
+    copy(begin, end, encryptionChallenge.begin());
+    begin = end;
+    end = begin + encryptedPage.size();
+    copy(begin, end, encryptedPage.begin());
+  }
+  return result;
+}
+
+error_code DS28E83_DS28E84::readBlockProtection(int blockNumber,
+                                                Optional<KeySecret> & keySecret,
+                                                BlockProtection & protection) {
+  if (blockNumber < 0 || blockNumber >= protectionBlocks) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const size_t requestSize = 2;
+  const size_t responseSize = 3;
+  uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
+  buffer[0] = 0xAA;
+  buffer[1] = blockNumber;
+  span<uint_least8_t> response(buffer, responseSize);
+  const error_code result =
+      runCommand(make_span(buffer, requestSize), readMemoryTimeMs, response);
+  if (result) {
+    return result;
+  }
+  if ((response[0] & 0x3F) != blockNumber) {
+    return make_error_code(InvalidResponseError);
+  }
+  switch (response[0] >> 6) {
+  case 0:
+    keySecret = none;
+    break;
+  case 1:
+    keySecret = KeySecretA;
+    break;
+  case 2:
+    keySecret = KeySecretB;
+    break;
+  default:
+    return make_error_code(InvalidResponseError);
+  }
+  if ((response[1] & 0x20) != 0) {
+    return make_error_code(InvalidResponseError);
+  }
+  protection = response[1];
+  return error_code();
+}
+
+error_code
+DS28E83_DS28E84::setBlockProtection(int blockNum, KeySecret keySecret,
+                                    const BlockProtection & protection) {
+  if (blockNum < 0 || blockNum >= protectionBlocks || keySecret == KeySecretS) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const uint_least8_t request[] = {
+      0xC3,
+      static_cast<uint_least8_t>((keySecret == KeySecretB ? 0x80 : 0x40) |
+                                 blockNum),
+      static_cast<uint_least8_t>(protection.to_ulong())};
+  return runCommand(request, writeStateTimeMs);
+}
+
+error_code DS28E83_DS28E84::computeAndReadPageAuthentication(
+    int pageNum, KeySecret key, Page::const_span challenge,
+    Ecc256::Signature::span signature) {
+  if (pageNum < 0 || pageNum >= memoryPages || key == KeySecretS) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const size_t requestSize = 3 + Page::size;
+  const size_t responseSize = 1 + 2 * Ecc256::Scalar::size;
+  uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
+  buffer[0] = computeAndReadPageAuthenticationCmd;
+  buffer[1] = pageNum;
+  buffer[2] = key + 3;
+  copy(challenge.begin(), challenge.end(), buffer + 3);
+  span<uint_least8_t> response(buffer, responseSize);
+  const error_code result = runCommand(make_span(buffer, requestSize),
+                                       generateEcdsaSignatureTimeMs, response);
+  if (!result) {
+    span<uint_least8_t>::const_iterator begin = response.begin();
+    span<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
+DS28E83_DS28E84::computeAndReadPageAuthentication(int pageNum, KeySecret secret,
+                                                  Page::const_span challenge,
+                                                  Page::span hmac) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const size_t requestSize = 3 + Page::size;
+  const size_t responseSize = 1 + Page::size;
+  uint_least8_t buffer[MaximInterfaceCore_MAX(requestSize, responseSize)];
+  buffer[0] = computeAndReadPageAuthenticationCmd;
+  buffer[1] = pageNum;
+  buffer[2] = secret;
+  copy(challenge.begin(), challenge.end(), buffer + 3);
+  span<uint_least8_t> response(buffer, responseSize);
+  const error_code result =
+      runCommand(make_span(buffer, requestSize), computeTimeMs, response);
+  if (!result) {
+    copy(response.begin(), response.end(), hmac.begin());
+  }
+  return result;
+}
+
+error_code
+DS28E83_DS28E84::computeMultiblockHash(bool firstBlock, bool lastBlock,
+                                       span<const uint_least8_t> data) {
+  const span<const uint_least8_t>::index_type maxDataSize = 64;
+
+  if (data.size() < 1 || data.size() > maxDataSize) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[2 + maxDataSize];
+  buffer[0] = 0x33;
+  buffer[1] = 0;
+  if (firstBlock) {
+    buffer[1] |= 0x40;
+  }
+  if (lastBlock) {
+    buffer[1] |= 0x80;
+  }
+  copy(data.begin(), data.end(), buffer + 2);
+  return runCommand(make_span(buffer, 2 + data.size()), computeTimeMs);
+}
+
+error_code DS28E83_DS28E84::verifyEcdsaSignature(
+    KeySecret key, bool authorityKey, GpioState gpioState,
+    Ecc256::Signature::const_span signature, span<const uint_least8_t> data) {
+  return verifyEcdsaSignature(key, authorityKey, DataInput, gpioState,
+                              signature, data);
+}
+
+error_code DS28E83_DS28E84::verifyEcdsaSignature(
+    KeySecret key, bool authorityKey, GpioState gpioState,
+    Ecc256::Signature::const_span signature, Page::const_span hash) {
+  return verifyEcdsaSignature(key, authorityKey, HashInput, gpioState,
+                              signature, hash);
+}
+
+error_code
+DS28E83_DS28E84::verifyEcdsaSignature(KeySecret key, bool authorityKey,
+                                      GpioState gpioState,
+                                      Ecc256::Signature::const_span signature) {
+  return verifyEcdsaSignature(key, authorityKey, THASH, gpioState, signature,
+                              span<const uint_least8_t>());
+}
+
+error_code DS28E83_DS28E84::verifyEcdsaSignature(
+    KeySecret key, bool authorityKey, HashType hashType, GpioState gpioState,
+    Ecc256::Signature::const_span signature, span<const uint_least8_t> buffer) {
+  const span<const uint_least8_t>::index_type maxBufferSize = 61;
+
+  if (buffer.size() > maxBufferSize) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t request[2 + 2 * Ecc256::Scalar::size + maxBufferSize];
+  uint_least8_t * requestIt = request;
+  *requestIt++ = 0x59;
+  switch (key) {
+  case KeySecretA:
+    if (authorityKey) {
+      *requestIt = 2;
+    } else {
+      *requestIt = 0;
+    }
+    break;
+  case KeySecretB:
+    if (authorityKey) {
+      *requestIt = 3;
+    } else {
+      *requestIt = 1;
+    }
+    break;
+  case KeySecretS:
+    if (!authorityKey) {
+      *requestIt = 4;
+      break;
+    }
+    // else: Go to default case.
+  default:
+    return make_error_code(InvalidParameterError);
+  }
+  *requestIt |= hashType << 3;
+  if (gpioState != Unchanged) {
+    *requestIt |= 0x40;
+  }
+  if (gpioState == Conducting) {
+    *requestIt |= 0x20;
+  }
+  requestIt = copy(signature.r.begin(), signature.r.end(), ++requestIt);
+  requestIt = copy(signature.s.begin(), signature.s.end(), requestIt);
+  requestIt = copy(buffer.begin(), buffer.end(), requestIt);
+  return runCommand(make_span(request, requestIt),
+                    verifyEcdsaTimeMs +
+                        (hashType == DataInput ? computeTimeMs : 0));
+}
+
+error_code DS28E83_DS28E84::authenticateEcdsaPublicKey(
+    KeySecret key, Ecc256::Signature::const_span cert,
+    span<const uint_least8_t> certCustomization) {
+  return authenticateEcdsaPublicKey(key, true, cert, certCustomization, NULL);
+}
+
+error_code DS28E83_DS28E84::authenticateEcdsaPublicKey(
+    KeySecret key, bool authWrites, Ecc256::Signature::const_span cert,
+    span<const uint_least8_t> certCustomization,
+    span<const uint_least8_t> ecdhCustomization) {
+  return authenticateEcdsaPublicKey(key, authWrites, cert, certCustomization,
+                                    &ecdhCustomization);
+}
+
+error_code DS28E83_DS28E84::authenticateEcdsaPublicKey(
+    KeySecret key, bool authWrites, Ecc256::Signature::const_span cert,
+    span<const uint_least8_t> certCustomization,
+    const span<const uint_least8_t> * ecdhCustomization) {
+  const span<const uint_least8_t>::index_type minCustomizationSize = 1;
+  const span<const uint_least8_t>::index_type maxCertCustomizationSize = 32;
+  const span<const uint_least8_t>::index_type maxEcdhCustomizationSize = 48;
+  const span<const uint_least8_t>::index_type maxTotalCustomizationSize = 60;
+
+  if (!(certCustomization.size() >= minCustomizationSize &&
+        certCustomization.size() <= maxCertCustomizationSize &&
+        (!ecdhCustomization ||
+         (ecdhCustomization->size() >= minCustomizationSize &&
+          ecdhCustomization->size() <= maxEcdhCustomizationSize &&
+          certCustomization.size() + ecdhCustomization->size() <=
+              maxTotalCustomizationSize)))) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  if (key == KeySecretS) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t
+      request[2 + 2 * Ecc256::Scalar::size + maxTotalCustomizationSize];
+  uint_least8_t * requestIt = request;
+  *requestIt++ = 0xA8;
+  *requestIt++ = static_cast<uint_least8_t>(
+      ((certCustomization.size() - 1) << 3) | (key << 2) |
+      ((ecdhCustomization != NULL) << 1) | (authWrites << 0));
+  requestIt = copy(cert.r.begin(), cert.r.end(), requestIt);
+  requestIt = copy(cert.s.begin(), cert.s.end(), requestIt);
+  requestIt =
+      copy(certCustomization.begin(), certCustomization.end(), requestIt);
+  int delay = verifyEcdsaTimeMs;
+  if (ecdhCustomization) {
+    const span<const uint_least8_t>::index_type certCustomizationPaddingSize =
+        maxCertCustomizationSize - certCustomization.size();
+    std::fill_n(requestIt, certCustomizationPaddingSize, 0);
+    requestIt += certCustomizationPaddingSize;
+    requestIt =
+        copy(ecdhCustomization->begin(), ecdhCustomization->end(), requestIt);
+    delay += verifyEcdsaTimeMs;
+  }
+  return runCommand(make_span(request, requestIt), delay);
+}
+
+error_code DS28E83_DS28E84::authenticatedEcdsaWriteMemory(
+    int pageNum, bool useKeyS, Page::const_span newPageData,
+    Ecc256::Signature::const_span signature) {
+  return authenticatedEcdsaWriteMemory(pageNum, useKeyS, newPageData, signature,
+                                       NULL);
+}
+
+error_code DS28E83_DS28E84::authenticatedEcdsaWriteMemory(
+    int pageNum, bool useKeyS, Page::const_span newPageData,
+    Ecc256::Signature::const_span signature,
+    EncryptionChallenge::const_span challenge) {
+  return authenticatedEcdsaWriteMemory(pageNum, useKeyS, newPageData, signature,
+                                       &challenge);
+}
+
+error_code DS28E83_DS28E84::authenticatedEcdsaWriteMemory(
+    int pageNum, bool useKeyS, Page::const_span newPageData,
+    Ecc256::Signature::const_span signature,
+    const EncryptionChallenge::const_span * challenge) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t request[2 + Page::size + 2 * Ecc256::Scalar::size +
+                        EncryptionChallenge::size];
+  uint_least8_t * requestIt = request;
+  *requestIt++ = 0x89;
+  *requestIt = pageNum;
+  if (useKeyS) {
+    *requestIt |= 0x80;
+  }
+  requestIt = copy(newPageData.begin(), newPageData.end(), ++requestIt);
+  requestIt = copy(signature.r.begin(), signature.r.end(), requestIt);
+  requestIt = copy(signature.s.begin(), signature.s.end(), requestIt);
+  int delay = verifyEcdsaTimeMs + writeMemoryTimeMs;
+  if (challenge) {
+    requestIt = copy(challenge->begin(), challenge->end(), requestIt);
+    delay += computeTimeMs;
+  }
+  return runCommand(make_span(request, requestIt), delay);
+}
+
+error_code
+DS28E83_DS28E84::authenticatedSha256WriteMemory(int pageNum, bool useSecretS,
+                                                Page::const_span newPageData,
+                                                Page::const_span hmac) {
+  return authenticatedSha256WriteMemory(pageNum, useSecretS, newPageData, hmac,
+                                        NULL);
+}
+
+error_code DS28E83_DS28E84::authenticatedSha256WriteMemory(
+    int pageNum, bool useSecretS, Page::const_span newPageData,
+    Page::const_span hmac, EncryptionChallenge::const_span challenge) {
+  return authenticatedSha256WriteMemory(pageNum, useSecretS, newPageData, hmac,
+                                        &challenge);
+}
+
+error_code DS28E83_DS28E84::authenticatedSha256WriteMemory(
+    int pageNum, bool useSecretS, Page::const_span newPageData,
+    Page::const_span hmac, const EncryptionChallenge::const_span * challenge) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t request[3 + 2 * Page::size + EncryptionChallenge::size];
+  uint_least8_t * requestIt = request;
+  *requestIt++ = 0x99;
+  *requestIt++ = pageNum;
+  *requestIt++ = useSecretS ? 2 : 0;
+  requestIt = copy(newPageData.begin(), newPageData.end(), requestIt);
+  requestIt = copy(hmac.begin(), hmac.end(), requestIt);
+  int delay = writeMemoryTimeMs + computeTimeMs;
+  if (challenge) {
+    requestIt = copy(challenge->begin(), challenge->end(), requestIt);
+    delay += computeTimeMs;
+  }
+  return runCommand(make_span(request, requestIt), delay);
+}
+
+error_code DS28E83_DS28E84::computeAndWriteSha256Secret(
+    int pageNum, KeySecret masterSecret, KeySecret destinationSecret,
+    Page::const_span partialSecret) {
+  if (pageNum < 0 || pageNum >= memoryPages) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t request[3 + Page::size];
+  request[0] = 0x3C;
+  request[1] = pageNum;
+  request[2] = (destinationSecret << 2) | masterSecret;
+  copy(partialSecret.begin(), partialSecret.end(), request + 3);
+  return runCommand(request, writeMemoryTimeMs + computeTimeMs);
+}
+
+error_code DS28E83_DS28E84::generateEcc256KeyPair(KeySecret key) {
+  if (key == KeySecretS) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  const uint_least8_t request[] = {0xCB, key == KeySecretB};
+  return runCommand(request, generateEccKeyPairTimeMs);
+}
+
+error_code DS28E83_DS28E84::readRng(span<uint_least8_t> data) {
+  const span<uint_least8_t>::index_type maxDataSize = 64;
+  if ((data.size() < 1) || (data.size() > maxDataSize)) {
+    return make_error_code(InvalidParameterError);
+  }
+
+  uint_least8_t buffer[1 + maxDataSize];
+  buffer[0] = readRngCmd;
+  buffer[1] = static_cast<uint_least8_t>(data.size() - 1);
+  span<uint_least8_t> response(buffer, 1 + data.size());
+  const error_code result =
+      runCommand(make_span(buffer, 2), trngGenerationTimeMs, response);
+  if (!result) {
+    copy(response.begin(), response.end(), data.begin());
+  }
+  return result;
+}
+
+error_code DS28E83_DS28E84::entropyHealthTest() {
+  const uint_least8_t request[] = {readRngCmd, 0x80};
+  return runCommand(request, trngOnDemandCheckTimeMs);
+}
+
+error_code DS28E83_DS28E84::runCommand(span<const uint_least8_t> request,
+                                       int delayTime,
+                                       span<uint_least8_t> & response) {
+  const span<const uint_least8_t>::index_type responseInputSize =
+      response.size();
+  error_code result = doRunCommand(request, delayTime, response);
+  if (result) {
+    return result;
+  }
+  if (response.empty()) {
+    return make_error_code(InvalidResponseError);
+  }
+  // Parse command result byte.
+  switch (response[0]) {
+  case 0xAA:
+    // Success response.
+    if (response.size() != responseInputSize) {
+      result = make_error_code(InvalidResponseError);
+    }
+    break;
+
+  case 0x00:
+    result = make_error_code(AuthenticationError);
+    break;
+
+  default:
+    result.assign(response[0], errorCategory());
+    break;
+  }
+  response = response.subspan(1);
+  return result;
+}
+
+error_code DS28E83_DS28E84::runCommand(span<const uint_least8_t> request,
+                                       int delayTime) {
+  uint_least8_t buffer;
+  span<uint_least8_t> response(&buffer, 1);
+  return runCommand(request, delayTime, response);
+}
+
+const error_category & DS28E83_DS28E84::errorCategory() {
+  static class : public error_category {
+  public:
+    virtual const char * name() const { return "DS28E83_DS28E84"; }
+
+    virtual std::string message(int condition) const {
+      switch (condition) {
+      case InvalidOperationError:
+        return "Invalid Operation Error";
+
+      case InvalidParameterError:
+        return "Invalid Parameter Error";
+
+      case InvalidSequenceError:
+        return "Invalid Sequence Error";
+
+      case AuthenticationError:
+        return "Authentication Error";
+
+      case InternalError:
+        return "Internal Error";
+
+      case DeviceDisabledError:
+        return "Device Disabled Error";
+
+      case InvalidResponseError:
+        return "Invalid Response Error";
+      }
+      return defaultErrorMessage(condition);
+    }
+  } instance;
+  return instance;
+}
+
+error_code DS28E84::decrementCounter() {
+  const uint_least8_t request = 0xC9;
+  return runCommand(make_span(&request, 1), writeMemoryTimeMs);
+}
+
+error_code DS28E84::deviceStateControl(StateOperation operation) {
+  const uint_least8_t request[] = {0x55, operation == Backup};
+  return runCommand(request, writeMemoryTimeMs);
+}
+
+error_code computeMultiblockHash(DS28E83_DS28E84 & device,
+                                 span<const uint_least8_t> data) {
+  error_code result;
+  span<const uint_least8_t>::index_type dataIdx = 0;
+  while (dataIdx < data.size() && !result) {
+    const span<const uint_least8_t>::index_type remainingSize =
+        data.size() - dataIdx;
+    const span<const uint_least8_t>::index_type chunkSize =
+        std::min<span<const uint_least8_t>::index_type>(remainingSize, 64);
+    result =
+        device.computeMultiblockHash(dataIdx == 0, remainingSize == chunkSize,
+                                     data.subspan(dataIdx, chunkSize));
+    dataIdx += chunkSize;
+  }
+  return result;
+}
+
+error_code readRomIdAndManId(DS28E83_DS28E84 & device, RomId::span romId,
+                             ManId::span manId) {
+  DS28E83_DS28E84::Page::array page;
+  error_code result = device.readMemory(DS28E83_DS28E84::romOptionsPage, page);
+  if (!result) {
+    const DS28E83_DS28E84::RomOptions romOptions(page);
+    copy(romOptions.romId(), romId);
+    copy(romOptions.manId(), manId);
+  }
+  return result;
+}
+
+static void setAnonymous(RomId::span romId) {
+  std::fill(romId.begin(), romId.end(), 0xFF);
+}
+
+DS28E83_DS28E84::PageAuthenticationData &
+DS28E83_DS28E84::PageAuthenticationData::setAnonymousRomId() {
+  setAnonymous(romId());
+  return *this;
+}
+
+DS28E83_DS28E84::ComputeSecretData::ComputeSecretData() : data() {
+  setPageNum(0);
+  setManId(ManId::array());
+}
+
+DS28E83_DS28E84::ComputeSecretData &
+DS28E83_DS28E84::ComputeSecretData::setManId(ManId::const_span manId) {
+  ManId::array validatedManId;
+  copy(manId, make_span(validatedManId));
+  validatedManId[1] |= 0x80;
+  data.setManId(validatedManId);
+  return *this;
+}
+
+DS28E83_DS28E84::DecryptionHmacData &
+DS28E83_DS28E84::DecryptionHmacData::setAnonymousRomId() {
+  setAnonymous(romId());
+  return *this;
+}
+
+} // namespace MaximInterfaceDevices
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS28E83_DS28E84.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,1022 @@
+/*******************************************************************************
+* Copyright (C) 2018 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 MaximInterfaceDevices_DS28E83_DS28E84
+#define MaximInterfaceDevices_DS28E83_DS28E84
+
+#include <stdint.h>
+#include <MaximInterfaceCore/Algorithm.hpp>
+#include <MaximInterfaceCore/array_span.hpp>
+#include <MaximInterfaceCore/Ecc256.hpp>
+#include <MaximInterfaceCore/FlagSet.hpp>
+#include <MaximInterfaceCore/ManId.hpp>
+#include <MaximInterfaceCore/Optional.hpp>
+#include <MaximInterfaceCore/RomId.hpp>
+#include <MaximInterfaceCore/RunCommand.hpp>
+#include <MaximInterfaceCore/system_error.hpp>
+#include "Config.hpp"
+
+namespace MaximInterfaceDevices {
+
+class DS28E83_DS28E84 {
+public:
+  /// Device command results.
+  enum ErrorValue {
+    InternalError = 0x22,
+    InvalidSequenceError = 0x33,
+    InvalidOperationError = 0x55,
+    InvalidParameterError = 0x77,
+    DeviceDisabledError = 0x88,
+    AuthenticationError = 0x100,
+    InvalidResponseError ///< Command response does not match expected format.
+  };
+
+  /// @name Device memory pages
+  /// @{
+
+  static const int publicKeyAxPage = 28;
+  static const int publicKeyAyPage = 29;
+  static const int publicKeyBxPage = 30;
+  static const int publicKeyByPage = 31;
+  static const int authorityPublicKeyAxPage = 32;
+  static const int authorityPublicKeyAyPage = 33;
+  static const int authorityPublicKeyBxPage = 34;
+  static const int authorityPublicKeyByPage = 35;
+  static const int privateKeyAPage = 36;
+  static const int privateKeyBPage = 37;
+  static const int secretAPage = 38;
+  static const int secretBPage = 39;
+  static const int romOptionsPage = 40;
+  static const int gpioControlPage = 41;
+  static const int publicKeySxPage = 42;
+  static const int publicKeySyPage = 43;
+
+  /// @}
+
+  /// Key or secret to use for operation.
+  enum KeySecret { KeySecretA = 0, KeySecretB = 1, KeySecretS = 2 };
+
+  /// Available PIO states when verifying an ECDSA signature.
+  enum GpioState { Unchanged, Conducting, HighImpedance };
+
+  /// Holds a device memory page.
+  typedef Core::array_span<uint_least8_t, 32> Page;
+
+  /// Challenge for an encrypted device memory page.
+  typedef Core::array_span<uint_least8_t, 8> EncryptionChallenge;
+
+  // Format page authentication input data.
+  class PageAuthenticationData;
+
+  // Format authenticated write input data.
+  class WriteAuthenticationData;
+
+  // Format compute secret input data.
+  class ComputeSecretData;
+
+  // Format decryption HMAC input data.
+  class DecryptionHmacData;
+
+  // Format encryption HMAC input data.
+  class EncryptionHmacData;
+
+  // Access fields in the ROM Options page.
+  class RomOptions;
+
+  // Access fields in the GPIO Control page.
+  class GpioControl;
+
+  /// Page protection types.
+  enum BlockProtectionType {
+    RP = 0x01,  ///< Read protection.
+    WP = 0x02,  ///< Write protection.
+    EM = 0x04,  ///< EPROM emulation mode.
+    APH = 0x08, ///< Authentication Write Protection HMAC
+    EPH = 0x10, ///< Encryption and Authentication Write Protection HMAC
+    ECH = 0x40, ///< Encryption and write using shared key from ECDH
+    ECW = 0x80  ///< Authentication Write Protection ECDSA
+  };
+  typedef Core::FlagSet<BlockProtectionType, 8> BlockProtection;
+
+protected:
+  explicit DS28E83_DS28E84(const Core::RunCommand & runCommand)
+      : doRunCommand(runCommand) {}
+
+  ~DS28E83_DS28E84() {}
+
+public:
+  void setRunCommand(const Core::RunCommand & runCommand) {
+    doRunCommand = runCommand;
+  }
+
+  /// @brief Write memory with no protection.
+  /// @param pageNum Number of page to write.
+  /// @param page Data to write.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  writeMemory(int pageNum, Page::const_span page);
+
+  /// @brief Read memory with no protection.
+  /// @param pageNum Number of page to read.
+  /// @param[out] page Data that was read.
+  MaximInterfaceDevices_EXPORT Core::error_code readMemory(int pageNum,
+                                                           Page::span page);
+
+  /// @brief Read memory with encryption.
+  /// @param pageNum Number of page to read from.
+  /// @param secret Secret to use for encryption.
+  /// @param[out] challenge Encryption challenge that was read.
+  /// @param[out] encryptedPage Encrypted page data that was read.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  encryptedReadMemory(int pageNum, KeySecret secret,
+                      EncryptionChallenge::span challenge,
+                      Page::span encryptedPage);
+
+  /// @brief Read the protection settings of a block.
+  /// @param blockNum Number of block to read.
+  /// @param[out] keySecret Secret key set on the block or empty if not set.
+  /// @param[out] protection Protection that was read.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readBlockProtection(int blockNum, Core::Optional<KeySecret> & keySecret,
+                      BlockProtection & protection);
+
+  /// @brief Set the protection settings of a block.
+  /// @param blockNum Number of block to write.
+  /// @param keySecret Secret/Key A or B.
+  /// @param protection Protection to write.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  setBlockProtection(int blockNum, KeySecret keySecret,
+                     const BlockProtection & protection);
+
+  /// @brief Compute and read page authentication with ECDSA.
+  /// @param pageNum Number of page to authenticate.
+  /// @param key
+  /// Private key to use for authentication.
+  /// Key S cannot be used with this command.
+  /// @param challenge Random challenge used to prevent replay attacks.
+  /// @param[out] signature Computed page signature.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeAndReadPageAuthentication(int pageNum, KeySecret key,
+                                   Page::const_span challenge,
+                                   Core::Ecc256::Signature::span signature);
+
+  /// @brief Compute and read page authentication with HMAC.
+  /// @param pageNum Number of page to authenticate.
+  /// @param secret
+  /// Secret to use for authentication.
+  /// Secret S cannot be used with this command.
+  /// @param challenge Random challenge used to prevent replay attacks.
+  /// @param[out] hmac Computed page HMAC.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeAndReadPageAuthentication(int pageNum, KeySecret secret,
+                                   Page::const_span challenge, Page::span hmac);
+
+  /// @brief 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. Should be 64 bytes unless this is the last block.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeMultiblockHash(bool firstBlock, bool lastBlock,
+                        Core::span<const uint_least8_t> data);
+
+  /// @brief Verify ECDSA signature with data input.
+  /// @param key Public key to use for verification.
+  /// @param authorityKey Use the authority key instead of the standard key.
+  /// @param gpioState New state of the GPIO pin if verification successful.
+  /// @param signature Signature to verify.
+  /// @param data Data to verify with length from 1 to 64.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState,
+                       Core::Ecc256::Signature::const_span signature,
+                       Core::span<const uint_least8_t> data);
+
+  /// @brief Verify ECDSA signature with hash input.
+  /// @param key Public key to use for verification.
+  /// @param authorityKey Use the authority key instead of the standard key.
+  /// @param gpioState New state of the GPIO pin if verification successful.
+  /// @param signature Signature to verify.
+  /// @param hash Hash of data to verify.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState,
+                       Core::Ecc256::Signature::const_span signature,
+                       Page::const_span hash);
+
+  /// @brief
+  /// Verify ECDSA signature with THASH input from Compute Multiblock Hash.
+  /// @param key Public key to use for verification.
+  /// @param authorityKey Use the authority key instead of the standard key.
+  /// @param gpioState New state of the GPIO pin if verification successful.
+  /// @param signature Signature to verify.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState,
+                       Core::Ecc256::Signature::const_span signature);
+
+  /// @brief Authenticate a public key for authenticated writes.
+  /// @param key
+  /// Authority key to use for authentication. Key A or B can be selected.
+  /// @param cert Certificate to use for authentication of Public Key S.
+  /// @param certCustomization
+  /// Certificate customization with length from 1 to 32.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  authenticateEcdsaPublicKey(KeySecret key,
+                             Core::Ecc256::Signature::const_span cert,
+                             Core::span<const uint_least8_t> certCustomization);
+
+  /// @brief
+  /// Authenticate a public key for ECDH and optionally authenticated writes.
+  /// @param key
+  /// Keys to use for authentication and ECDH key exchange.
+  /// Key A or B can be selected.
+  /// @param authWrites True to select authentication for writes.
+  /// @param cert Certificate to use for authentication of Public Key S.
+  /// @param certCustomization
+  /// Certificate customization with length from 1 to 32.
+  /// @param ecdhCustomization ECDH customization with length from 1 to 48.
+  /// @note The maximum total customization length is 60 bytes.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  authenticateEcdsaPublicKey(KeySecret key, bool authWrites,
+                             Core::Ecc256::Signature::const_span cert,
+                             Core::span<const uint_least8_t> certCustomization,
+                             Core::span<const uint_least8_t> ecdhCustomization);
+
+  /// @brief Write with ECDSA authentication.
+  /// @param pageNum Number of page to write.
+  /// @param useKeyS
+  /// Use Public Key S instead of the authority key set in the block protection.
+  /// @param newPageData Data to write.
+  /// @param signature Signature to use for authentication of page data.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  authenticatedEcdsaWriteMemory(int pageNum, bool useKeyS,
+                                Page::const_span newPageData,
+                                Core::Ecc256::Signature::const_span signature);
+
+  /// @brief Write with ECDSA authentication and encryption.
+  /// @param pageNum Number of page to write.
+  /// @param useKeyS
+  /// Use Public Key S instead of the authority key set in the block protection.
+  /// @param newPageData Encrypted data to write.
+  /// @param signature Signature to use for authentication of page data.
+  /// @param challenge Challenge to use for decryption of page data.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  authenticatedEcdsaWriteMemory(int pageNum, bool useKeyS,
+                                Page::const_span newPageData,
+                                Core::Ecc256::Signature::const_span signature,
+                                EncryptionChallenge::const_span challenge);
+
+  /// @brief Write with SHA-256 HMAC authentication.
+  /// @param pageNum Number of page to write.
+  /// @param useSecretS
+  /// Use Secret S instead of the secret set in the block protection.
+  /// @param newPageData Data to write.
+  /// @param hmac HMAC to use for authentication of page data.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  authenticatedSha256WriteMemory(int pageNum, bool useSecretS,
+                                 Page::const_span newPageData,
+                                 Page::const_span hmac);
+
+  /// @brief Write with SHA-256 HMAC authentication and encryption.
+  /// @param pageNum Number of page to write.
+  /// @param useSecretS
+  /// Use Secret S instead of the secret set in the block protection.
+  /// @param newPageData Data to write.
+  /// @param hmac HMAC to use for authentication of page data.
+  /// @param challenge Challenge to use for decryption of page data.
+  MaximInterfaceDevices_EXPORT Core::error_code authenticatedSha256WriteMemory(
+      int pageNum, bool useSecretS, Page::const_span newPageData,
+      Page::const_span hmac, EncryptionChallenge::const_span challenge);
+
+  /// @brief Compute a derivative SHA-256 secret from an existing secret.
+  /// @param pageNum Number of page to use in computation.
+  /// @param masterSecret Master secret to use in computation.
+  /// @param destinationSecret
+  /// Destination secret to receive the computation result.
+  /// @param partialSecret Partial secret to use in computation.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  computeAndWriteSha256Secret(int pageNum, KeySecret masterSecret,
+                              KeySecret destinationSecret,
+                              Page::const_span partialSecret);
+
+  /// @brief Generate a new ECDSA key pair.
+  /// @param key Key to generate. Key S cannot be used with this command.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  generateEcc256KeyPair(KeySecret key);
+
+  /// @brief Read a block of random data from the RNG.
+  /// @param[out] data Random data from RNG with length from 1 to 64.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  readRng(Core::span<uint_least8_t> data);
+
+  /// Run entropy health test on the RNG.
+  MaximInterfaceDevices_EXPORT Core::error_code entropyHealthTest();
+
+  MaximInterfaceDevices_EXPORT static const Core::error_category &
+  errorCategory();
+
+protected:
+  MaximInterfaceDevices_EXPORT Core::error_code
+  runCommand(Core::span<const uint_least8_t> request, int delayTime,
+             Core::span<uint_least8_t> & response);
+
+  MaximInterfaceDevices_EXPORT Core::error_code
+  runCommand(Core::span<const uint_least8_t> request, int delayTime);
+
+private:
+  enum HashType { HashInput, DataInput, THASH };
+
+  Core::error_code
+  verifyEcdsaSignature(KeySecret key, bool authorityKey, HashType hashType,
+                       GpioState gpioState,
+                       Core::Ecc256::Signature::const_span signature,
+                       Core::span<const uint_least8_t> buffer);
+
+  Core::error_code authenticateEcdsaPublicKey(
+      KeySecret key, bool authWrites, Core::Ecc256::Signature::const_span cert,
+      Core::span<const uint_least8_t> certCustomization,
+      const Core::span<const uint_least8_t> * ecdhCustomization);
+
+  Core::error_code authenticatedEcdsaWriteMemory(
+      int pageNum, bool useKeyS, Page::const_span newPageData,
+      Core::Ecc256::Signature::const_span signature,
+      const EncryptionChallenge::const_span * challenge);
+
+  Core::error_code authenticatedSha256WriteMemory(
+      int pageNum, bool useSecretS, Page::const_span newPageData,
+      Page::const_span hmac, const EncryptionChallenge::const_span * challenge);
+
+  Core::RunCommand doRunCommand;
+};
+
+inline Core::error_code make_error_code(DS28E83_DS28E84::ErrorValue e) {
+  return Core::error_code(e, DS28E83_DS28E84::errorCategory());
+}
+
+class DS28E83 : public DS28E83_DS28E84 {
+public:
+  static const int memoryPages = 44;
+  static const int protectionBlocks = 9;
+
+  explicit DS28E83(const Core::RunCommand & runCommand)
+      : DS28E83_DS28E84(runCommand) {}
+};
+
+class DS28E84 : public DS28E83_DS28E84 {
+public:
+  /// @name Device memory pages
+  /// @{
+
+  static const int publicKeySxBackupPage = 104;
+  static const int publicKeySyBackupPage = 105;
+  static const int decrementCounterPage = 106;
+
+  /// @}
+
+  static const int memoryPages = 107;
+  static const int protectionBlocks = 24;
+
+  enum StateOperation { Backup, Restore };
+
+  explicit DS28E84(const Core::RunCommand & runCommand)
+      : DS28E83_DS28E84(runCommand) {}
+
+  /// Decrement the decrement-only counter.
+  MaximInterfaceDevices_EXPORT Core::error_code decrementCounter();
+
+  /// Back up or restore the state of the device to non-volatile memory.
+  MaximInterfaceDevices_EXPORT Core::error_code
+  deviceStateControl(StateOperation operation);
+};
+
+/// @brief
+/// Hash arbitrary length data with successive Compute Multiblock Hash commands.
+/// @param device Device for computation.
+/// @param data Data to hash.
+MaximInterfaceDevices_EXPORT Core::error_code
+computeMultiblockHash(DS28E83_DS28E84 & device,
+                      Core::span<const uint_least8_t> data);
+
+/// @brief
+/// Read the device ROM ID and MAN ID using the Read Memory command on the
+/// ROM Options page.
+/// @param device Device to read.
+/// @param[out] romId Read ROM ID valid when operation is successful.
+/// @param[out] manId Read MAN ID valid when operation is successful.
+MaximInterfaceDevices_EXPORT Core::error_code
+readRomIdAndManId(DS28E83_DS28E84 & device, Core::RomId::span romId,
+                  Core::ManId::span manId);
+
+/// Format page authentication input data.
+class DS28E83_DS28E84::PageAuthenticationData {
+public:
+  typedef Core::array_span<uint_least8_t, Core::RomId::size + 2 * Page::size +
+                                              1 + Core::ManId::size>
+      Result;
+
+  PageAuthenticationData() : result_() {}
+
+  /// Formatted data result.
+  Result::const_span result() const { return result_; }
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() {
+    return make_span(result_).subspan<romIdIdx, Core::RomId::size>();
+  }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const {
+    return const_cast<PageAuthenticationData &>(*this).romId();
+  }
+
+  /// Set ROM ID.
+  PageAuthenticationData & setRomId(Core::RomId::const_span romId) {
+    copy(romId, this->romId());
+    return *this;
+  }
+
+  /// Set ROM ID for use in anonymous mode.
+  MaximInterfaceDevices_EXPORT PageAuthenticationData & setAnonymousRomId();
+
+  /// @}
+
+  /// @name Page
+  /// @brief Data from a device memory page.
+  /// @{
+
+  /// Get mutable page.
+  Page::span page() {
+    return make_span(result_).subspan<pageIdx, Page::size>();
+  }
+
+  /// Get immutable page.
+  Page::const_span page() const {
+    return const_cast<PageAuthenticationData &>(*this).page();
+  }
+
+  /// Set page.
+  PageAuthenticationData & setPage(Page::const_span page) {
+    copy(page, this->page());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Challenge
+  /// @brief Random challenge used to prevent replay attacks.
+  /// @{
+
+  /// Get mutable Challenge.
+  Page::span challenge() {
+    return make_span(result_).subspan<challengeIdx, Page::size>();
+  }
+
+  /// Get immutable Challenge.
+  Page::const_span challenge() const {
+    return const_cast<PageAuthenticationData &>(*this).challenge();
+  }
+
+  /// Set Challenge.
+  PageAuthenticationData & setChallenge(Page::const_span challenge) {
+    copy(challenge, this->challenge());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Number of the page to use data from.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return result_[pageNumIdx]; }
+
+  /// Set page number.
+  PageAuthenticationData & setPageNum(int pageNum) {
+    result_[pageNumIdx] = pageNum;
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() {
+    return make_span(result_).subspan<manIdIdx, Core::ManId::size>();
+  }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const {
+    return const_cast<PageAuthenticationData &>(*this).manId();
+  }
+
+  /// Set MAN ID.
+  PageAuthenticationData & setManId(Core::ManId::const_span manId) {
+    copy(manId, this->manId());
+    return *this;
+  }
+
+  /// @}
+
+private:
+  typedef Result::span::index_type index;
+
+  static const index romIdIdx = 0;
+  static const index pageIdx = romIdIdx + Core::RomId::size;
+  static const index challengeIdx = pageIdx + Page::size;
+  static const index pageNumIdx = challengeIdx + Page::size;
+  static const index manIdIdx = pageNumIdx + 1;
+
+  Result::array result_;
+};
+
+/// Format authenticated write input data.
+class DS28E83_DS28E84::WriteAuthenticationData {
+public:
+  typedef PageAuthenticationData::Result Result;
+
+  WriteAuthenticationData() : data() { setPageNum(0); }
+
+  /// Formatted data result.
+  Result::const_span result() const { return data.result(); }
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() { return data.romId(); }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const { return data.romId(); }
+
+  /// Set ROM ID.
+  WriteAuthenticationData & setRomId(Core::RomId::const_span romId) {
+    data.setRomId(romId);
+    return *this;
+  }
+
+  /// Set ROM ID for use in anonymous mode.
+  WriteAuthenticationData & setAnonymousRomId() {
+    data.setAnonymousRomId();
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Old page
+  /// @brief Existing data contained in the page.
+  /// @{
+
+  /// Get mutable old page.
+  Page::span oldPage() { return data.page(); }
+
+  /// Get immutable old page.
+  Page::const_span oldPage() const { return data.page(); }
+
+  /// Set old page.
+  WriteAuthenticationData & setOldPage(Page::const_span oldPage) {
+    data.setPage(oldPage);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name New page
+  /// @brief New data to write to the page.
+  /// @{
+
+  /// Get mutable new page.
+  Page::span newPage() { return data.challenge(); }
+
+  /// Get immutable new page.
+  Page::const_span newPage() const { return data.challenge(); }
+
+  /// Set new page.
+  WriteAuthenticationData & setNewPage(Page::const_span newPage) {
+    data.setChallenge(newPage);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Page number for write operation.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return data.pageNum() & 0x7F; }
+
+  /// Set page number.
+  WriteAuthenticationData & setPageNum(int pageNum) {
+    data.setPageNum(pageNum | 0x80);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() { return data.manId(); }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const { return data.manId(); }
+
+  /// Set MAN ID.
+  WriteAuthenticationData & setManId(Core::ManId::const_span manId) {
+    data.setManId(manId);
+    return *this;
+  }
+
+  /// @}
+
+private:
+  PageAuthenticationData data;
+};
+
+/// Format compute secret input data.
+class DS28E83_DS28E84::ComputeSecretData {
+public:
+  typedef PageAuthenticationData::Result Result;
+
+  MaximInterfaceDevices_EXPORT ComputeSecretData();
+
+  /// Formatted data result.
+  Result::const_span result() const { return data.result(); }
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() { return data.romId(); }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const { return data.romId(); }
+
+  /// Set ROM ID.
+  ComputeSecretData & setRomId(Core::RomId::const_span romId) {
+    data.setRomId(romId);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Binding Data
+  /// @brief Binding Data contained in the selected page.
+  /// @{
+
+  /// Get mutable Binding Data.
+  Page::span bindingData() { return data.page(); }
+
+  /// Get immutable Binding Data.
+  Page::const_span bindingData() const { return data.page(); }
+
+  /// Set Binding Data.
+  ComputeSecretData & setBindingData(Page::const_span bindingData) {
+    data.setPage(bindingData);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Partial Secret
+  /// @brief Partial Secret used for customization.
+  /// @{
+
+  /// Get mutable Partial Secret.
+  Page::span partialSecret() { return data.challenge(); }
+
+  /// Get immutable Partial Secret.
+  Page::const_span partialSecret() const { return data.challenge(); }
+
+  /// Set Partial Secret.
+  ComputeSecretData & setPartialSecret(Page::const_span partialSecret) {
+    data.setChallenge(partialSecret);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Page number for Binding Data.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return data.pageNum() & 0x3F; }
+
+  /// Set page number.
+  ComputeSecretData & setPageNum(int pageNum) {
+    data.setPageNum(pageNum | 0xC0);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const { return data.manId(); }
+
+  /// Set MAN ID.
+  MaximInterfaceDevices_EXPORT ComputeSecretData &
+  setManId(Core::ManId::const_span manId);
+
+  /// @}
+
+private:
+  PageAuthenticationData data;
+};
+
+/// Format decryption HMAC input data.
+class DS28E83_DS28E84::DecryptionHmacData {
+public:
+  typedef Core::array_span<uint_least8_t, EncryptionChallenge::size +
+                                              Core::RomId::size + 1 +
+                                              Core::ManId::size>
+      Result;
+
+  DecryptionHmacData() : result_() {}
+
+  /// Formatted data result.
+  Result::const_span result() const { return result_; }
+
+  /// @name Encryption Challenge
+  /// @brief Random challenge used to prevent replay attacks.
+  /// @{
+
+  /// Get mutable Encryption Challenge.
+  EncryptionChallenge::span encryptionChallenge() {
+    return make_span(result_)
+        .subspan<encryptionChallengeIdx, EncryptionChallenge::size>();
+  }
+
+  /// Get immutable Encryption Challenge.
+  EncryptionChallenge::const_span encryptionChallenge() const {
+    return const_cast<DecryptionHmacData &>(*this).encryptionChallenge();
+  }
+
+  /// Set Encryption Challenge.
+  DecryptionHmacData &
+  setEncryptionChallenge(EncryptionChallenge::const_span encryptionChallenge) {
+    copy(encryptionChallenge, this->encryptionChallenge());
+    return *this;
+  }
+
+  /// @}
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() {
+    return make_span(result_).subspan<romIdIdx, Core::RomId::size>();
+  }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const {
+    return const_cast<DecryptionHmacData &>(*this).romId();
+  }
+
+  /// Set ROM ID.
+  DecryptionHmacData & setRomId(Core::RomId::const_span romId) {
+    copy(romId, this->romId());
+    return *this;
+  }
+
+  /// Set ROM ID for use in anonymous mode.
+  MaximInterfaceDevices_EXPORT DecryptionHmacData & setAnonymousRomId();
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Number of the page to use data from.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return result_[pageNumIdx]; }
+
+  /// Set page number.
+  DecryptionHmacData & setPageNum(int pageNum) {
+    result_[pageNumIdx] = pageNum;
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() {
+    return make_span(result_).subspan<manIdIdx, Core::ManId::size>();
+  }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const {
+    return const_cast<DecryptionHmacData &>(*this).manId();
+  }
+
+  /// Set MAN ID.
+  DecryptionHmacData & setManId(Core::ManId::const_span manId) {
+    copy(manId, this->manId());
+    return *this;
+  }
+
+  /// @}
+
+private:
+  typedef Result::span::index_type index;
+
+  static const index encryptionChallengeIdx = 0;
+  static const index romIdIdx =
+      encryptionChallengeIdx + EncryptionChallenge::size;
+  static const index pageNumIdx = romIdIdx + Core::RomId::size;
+  static const index manIdIdx = pageNumIdx + 1;
+
+  Result::array result_;
+};
+
+/// Format encryption HMAC input data.
+class DS28E83_DS28E84::EncryptionHmacData {
+public:
+  typedef DecryptionHmacData::Result Result;
+
+  EncryptionHmacData() : data() { setPageNum(0); }
+
+  /// Formatted data result.
+  Result::const_span result() const { return data.result(); }
+
+  /// @name Encryption Challenge
+  /// @brief Random challenge used to prevent replay attacks.
+  /// @{
+
+  /// Get mutable Encryption Challenge.
+  EncryptionChallenge::span encryptionChallenge() {
+    return data.encryptionChallenge();
+  }
+
+  /// Get immutable Encryption Challenge.
+  EncryptionChallenge::const_span encryptionChallenge() const {
+    return data.encryptionChallenge();
+  }
+
+  /// Set Encryption Challenge.
+  EncryptionHmacData &
+  setEncryptionChallenge(EncryptionChallenge::const_span encryptionChallenge) {
+    data.setEncryptionChallenge(encryptionChallenge);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
+  /// @{
+
+  /// Get mutable ROM ID.
+  Core::RomId::span romId() { return data.romId(); }
+
+  /// Get immutable ROM ID.
+  Core::RomId::const_span romId() const { return data.romId(); }
+
+  /// Set ROM ID.
+  EncryptionHmacData & setRomId(Core::RomId::const_span romId) {
+    data.setRomId(romId);
+    return *this;
+  }
+
+  /// Set ROM ID for use in anonymous mode.
+  EncryptionHmacData & setAnonymousRomId() {
+    data.setAnonymousRomId();
+    return *this;
+  }
+
+  /// @}
+
+  /// @name Page number
+  /// @brief Number of the page to use data from.
+  /// @{
+
+  /// Get page number.
+  int pageNum() const { return data.pageNum() & 0x7F; }
+
+  /// Set page number.
+  EncryptionHmacData & setPageNum(int pageNum) {
+    data.setPageNum(pageNum | 0x80);
+    return *this;
+  }
+
+  /// @}
+
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
+  /// @{
+
+  /// Get mutable MAN ID.
+  Core::ManId::span manId() { return data.manId(); }
+
+  /// Get immutable MAN ID.
+  Core::ManId::const_span manId() const { return data.manId(); }
+
+  /// Set MAN ID.
+  EncryptionHmacData & setManId(Core::ManId::const_span manId) {
+    data.setManId(manId);
+    return *this;
+  }
+
+  /// @}
+
+private:
+  DecryptionHmacData data;
+};
+
+/// Access fields in the ROM Options page.
+class DS28E83_DS28E84::RomOptions {
+public:
+  explicit RomOptions(Page::span page) : page(page) {}
+
+  bool anonymous() const { return page[anonymousIdx] == anonymousValue; }
+
+  void setAnonymous(bool anonymous) {
+    page[anonymousIdx] = (anonymous ? anonymousValue : 0);
+  }
+
+  Core::ManId::const_span manId() const {
+    return page.subspan<22, Core::ManId::size>();
+  }
+
+  Core::RomId::const_span romId() const {
+    return page.subspan<24, Core::RomId::size>();
+  }
+
+private:
+  static const Page::span::index_type anonymousIdx = 1;
+  static const Page::span::value_type anonymousValue = 0xAA;
+
+  Page::span page;
+};
+
+/// Access fields in the GPIO Control page.
+class DS28E83_DS28E84::GpioControl {
+public:
+  explicit GpioControl(Page::span page) : page(page) {}
+
+  bool conducting() const { return page[conductingIdx] == conductingValue; }
+
+  void setConducting(bool conducting) {
+    page[conductingIdx] = (conducting ? conductingValue : 0x55);
+  }
+
+  bool level() const { return page[2] == 0x55; }
+
+private:
+  static const Page::span::index_type conductingIdx = 0;
+  static const Page::span::value_type conductingValue = 0xAA;
+
+  Page::span page;
+};
+
+} // namespace MaximInterfaceDevices
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS9400.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,91 @@
+/*******************************************************************************
+* 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 MaximInterfaceDevices {
+
+using namespace Core;
+
+error_code DS9400::waitAwake() {
+  error_code result;
+  uint_least8_t data;
+  do {
+    result = uart->readByte(data);
+  } while (!result && data != 0xA5);
+  return result;
+}
+
+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);
+    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;
+}
+
+error_code DS9400::configure(uint_least8_t config) {
+  const uint_least8_t packet[] = {'C', config};
+  return uart->writeBlock(packet);
+}
+
+} // namespace MaximInterfaceDevices
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS9400.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 MaximInterfaceDevices_DS9400
+#define MaximInterfaceDevices_DS9400
+
+#include <MaximInterfaceCore/I2CMaster.hpp>
+#include <MaximInterfaceCore/Uart.hpp>
+#include "Config.hpp"
+
+namespace MaximInterfaceDevices {
+
+class DS9400 : public Core::I2CMaster {
+public:
+  explicit DS9400(Core::Uart & uart) : uart(&uart) {}
+
+  void setUart(Core::Uart & uart) { this->uart = &uart; }
+
+  MaximInterfaceDevices_EXPORT Core::error_code waitAwake();
+
+  MaximInterfaceDevices_EXPORT Core::error_code start();
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  start(uint_least8_t address);
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code stop();
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  writeByte(uint_least8_t data);
+
+  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  readByte(AckStatus status, uint_least8_t & data);
+
+protected:
+  MaximInterfaceDevices_EXPORT Core::error_code configure(uint_least8_t config);
+
+private:
+  Core::Uart * uart;
+};
+
+} // namespace MaximInterfaceDevices
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS9481P_300.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,249 @@
+/*******************************************************************************
+* 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 <MaximInterfaceCore/Error.hpp>
+#include "DS9481P_300.hpp"
+
+namespace MaximInterfaceDevices {
+
+using namespace Core;
+
+DS9481P_300::DS9481P_300(Sleep & sleep, SerialPort & serialPort)
+    : serialPort(&serialPort), currentBus(OneWire), ds2480b(sleep, serialPort),
+      oneWireMaster_(*this), ds9400(serialPort), i2cMaster_(*this) {}
+
+error_code DS9481P_300::connect(const std::string & portName) {
+  error_code result = serialPort->connect(portName);
+  if (!result) {
+    result = selectOneWire();
+    if (result) {
+      serialPort->disconnect();
+    } else {
+      currentBus = OneWire;
+    }
+  }
+  return result;
+}
+
+error_code DS9481P_300::disconnect() { return serialPort->disconnect(); }
+
+bool DS9481P_300::connected() const { return serialPort->connected(); }
+
+std::string DS9481P_300::portName() const { return serialPort->portName(); }
+
+error_code DS9481P_300::selectOneWire() {
+  // Escape DS9400 mode.
+  error_code result = ds9400.escape();
+  if (!result) {
+    result = ds2480b.initialize();
+  }
+  return result;
+}
+
+error_code DS9481P_300::selectBus(Bus newBus) {
+  error_code result;
+  if (currentBus != newBus) {
+    switch (currentBus) {
+    case OneWire: // Next bus I2C.
+      // Escape DS2480 Mode.
+      result = ds2480b.escape();
+      if (!result) {
+        // Wait for awake notification.
+        result = ds9400.waitAwake();
+      }
+      break;
+
+    case I2C: // Next bus OneWire.
+      result = selectOneWire();
+      break;
+    }
+    if (!result) {
+      currentBus = newBus;
+    }
+  }
+  return result;
+}
+
+error_code DS9481P_300::OneWireMaster::reset() {
+  error_code result = parent->selectBus(OneWire);
+  if (!result) {
+    result = OneWireMasterDecorator::reset();
+  }
+  return result;
+}
+
+error_code DS9481P_300::OneWireMaster::touchBitSetLevel(bool & sendRecvBit,
+                                                        Level afterLevel) {
+  error_code result = parent->selectBus(OneWire);
+  if (!result) {
+    result = OneWireMasterDecorator::touchBitSetLevel(sendRecvBit, afterLevel);
+  }
+  return result;
+}
+
+error_code DS9481P_300::OneWireMaster::writeByteSetLevel(uint_least8_t sendByte,
+                                                         Level afterLevel) {
+  error_code result = parent->selectBus(OneWire);
+  if (!result) {
+    result = OneWireMasterDecorator::writeByteSetLevel(sendByte, afterLevel);
+  }
+  return result;
+}
+
+error_code
+DS9481P_300::OneWireMaster::readByteSetLevel(uint_least8_t & recvByte,
+                                             Level afterLevel) {
+  error_code result = parent->selectBus(OneWire);
+  if (!result) {
+    result = OneWireMasterDecorator::readByteSetLevel(recvByte, afterLevel);
+  }
+  return result;
+}
+
+error_code
+DS9481P_300::OneWireMaster::writeBlock(span<const uint_least8_t> sendBuf) {
+  error_code result = parent->selectBus(OneWire);
+  if (!result) {
+    result = OneWireMasterDecorator::writeBlock(sendBuf);
+  }
+  return result;
+}
+
+error_code DS9481P_300::OneWireMaster::readBlock(span<uint_least8_t> recvBuf) {
+  error_code result = parent->selectBus(OneWire);
+  if (!result) {
+    result = OneWireMasterDecorator::readBlock(recvBuf);
+  }
+  return result;
+}
+
+error_code DS9481P_300::OneWireMaster::setSpeed(Speed newSpeed) {
+  error_code result = parent->selectBus(OneWire);
+  if (!result) {
+    result = OneWireMasterDecorator::setSpeed(newSpeed);
+  }
+  return result;
+}
+
+error_code DS9481P_300::OneWireMaster::setLevel(Level newLevel) {
+  error_code result = parent->selectBus(OneWire);
+  if (!result) {
+    result = OneWireMasterDecorator::setLevel(newLevel);
+  }
+  return result;
+}
+
+error_code DS9481P_300::OneWireMaster::triplet(TripletData & data) {
+  error_code result = parent->selectBus(OneWire);
+  if (!result) {
+    result = OneWireMasterDecorator::triplet(data);
+  }
+  return result;
+}
+
+error_code DS9481P_300::I2CMaster::start(uint_least8_t address) {
+  error_code result = parent->selectBus(I2C);
+  if (!result) {
+    result = I2CMasterDecorator::start(address);
+  }
+  return result;
+}
+
+error_code DS9481P_300::I2CMaster::stop() {
+  error_code result = parent->selectBus(I2C);
+  if (!result) {
+    result = I2CMasterDecorator::stop();
+  }
+  return result;
+}
+
+error_code DS9481P_300::I2CMaster::writeByte(uint_least8_t data) {
+  error_code result = parent->selectBus(I2C);
+  if (!result) {
+    result = I2CMasterDecorator::writeByte(data);
+  }
+  return result;
+}
+
+error_code DS9481P_300::I2CMaster::writeBlock(span<const uint_least8_t> data) {
+  error_code result = parent->selectBus(I2C);
+  if (!result) {
+    result = I2CMasterDecorator::writeBlock(data);
+  }
+  return result;
+}
+
+error_code DS9481P_300::I2CMaster::doWritePacket(uint_least8_t address,
+                                                 span<const uint_least8_t> data,
+                                                 bool sendStop) {
+  error_code result = parent->selectBus(I2C);
+  if (!result) {
+    result = I2CMasterDecorator::doWritePacket(address, data, sendStop);
+  }
+  return result;
+}
+
+error_code DS9481P_300::I2CMaster::readByte(AckStatus status,
+                                            uint_least8_t & data) {
+  error_code result = parent->selectBus(I2C);
+  if (!result) {
+    result = I2CMasterDecorator::readByte(status, data);
+  }
+  return result;
+}
+
+error_code DS9481P_300::I2CMaster::readBlock(AckStatus status,
+                                             span<uint_least8_t> data) {
+  error_code result = parent->selectBus(I2C);
+  if (!result) {
+    result = I2CMasterDecorator::readBlock(status, data);
+  }
+  return result;
+}
+
+error_code DS9481P_300::I2CMaster::doReadPacket(uint_least8_t address,
+                                                span<uint_least8_t> data,
+                                                bool sendStop) {
+  error_code result = parent->selectBus(I2C);
+  if (!result) {
+    result = I2CMasterDecorator::doReadPacket(address, data, sendStop);
+  }
+  return result;
+}
+
+error_code DS9481P_300::DS2480BWithEscape::escape() {
+  return sendCommand(0xE5);
+}
+
+error_code DS9481P_300::DS9400WithEscape::escape() { return configure('O'); }
+
+} // namespace MaximInterfaceDevices
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceDevices/DS9481P_300.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,179 @@
+/*******************************************************************************
+* 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 MaximInterfaceDevices_DS9481P_300
+#define MaximInterfaceDevices_DS9481P_300
+
+#include <MaximInterfaceCore/I2CMasterDecorator.hpp>
+#include <MaximInterfaceCore/OneWireMasterDecorator.hpp>
+#include <MaximInterfaceCore/SerialPort.hpp>
+#include <MaximInterfaceCore/Sleep.hpp>
+#include "DS2480B.hpp"
+#include "DS9400.hpp"
+#include "Config.hpp"
+
+namespace MaximInterfaceDevices {
+
+/// DS9481P-300 USB to 1-Wire and I2C adapter.
+class DS9481P_300 {
+public:
+  MaximInterfaceDevices_EXPORT DS9481P_300(Core::Sleep & sleep,
+                                           Core::SerialPort & serialPort);
+
+  void setSleep(Core::Sleep & sleep) { ds2480b.setSleep(sleep); }
+
+  void setSerialPort(Core::SerialPort & serialPort) {
+    this->serialPort = &serialPort;
+    ds2480b.setUart(serialPort);
+    ds9400.setUart(serialPort);
+  }
+
+  MaximInterfaceDevices_EXPORT Core::error_code
+  connect(const std::string & portName);
+
+  MaximInterfaceDevices_EXPORT Core::error_code disconnect();
+
+  MaximInterfaceDevices_EXPORT bool connected() const;
+
+  MaximInterfaceDevices_EXPORT std::string portName() const;
+
+  /// Access the 1-Wire master when connected to an adapter.
+  Core::OneWireMaster & oneWireMaster() { return oneWireMaster_; }
+
+  /// Access the I2C master when connected to an adapter.
+  Core::I2CMaster & i2cMaster() { return i2cMaster_; }
+
+private:
+  class OneWireMaster : public Core::OneWireMasterDecorator {
+  public:
+    explicit OneWireMaster(DS9481P_300 & parent)
+        : OneWireMasterDecorator(parent.ds2480b), parent(&parent) {}
+
+    MaximInterfaceDevices_EXPORT virtual Core::error_code reset();
+
+    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    touchBitSetLevel(bool & sendRecvBit, Level afterLevel);
+
+    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
+
+    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+
+    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    writeBlock(Core::span<const uint_least8_t> sendBuf);
+
+    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    readBlock(Core::span<uint_least8_t> recvBuf);
+
+    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    setSpeed(Speed newSpeed);
+
+    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    setLevel(Level newLevel);
+
+    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    triplet(TripletData & data);
+
+  private:
+    DS9481P_300 * parent;
+  };
+
+  class I2CMaster : public Core::I2CMasterDecorator {
+  public:
+    explicit I2CMaster(DS9481P_300 & parent)
+        : I2CMasterDecorator(parent.ds9400), parent(&parent) {}
+
+    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    start(uint_least8_t address);
+
+    MaximInterfaceDevices_EXPORT virtual Core::error_code stop();
+
+    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    writeByte(uint_least8_t data);
+
+    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    writeBlock(Core::span<const uint_least8_t> data);
+
+    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    readByte(AckStatus status, uint_least8_t & data);
+
+    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    readBlock(AckStatus status, Core::span<uint_least8_t> data);
+
+  protected:
+    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    doWritePacket(uint_least8_t address, Core::span<const uint_least8_t> data,
+                  bool sendStop);
+
+    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    doReadPacket(uint_least8_t address, Core::span<uint_least8_t> data,
+                 bool sendStop);
+
+  private:
+    DS9481P_300 * parent;
+  };
+
+  class DS2480BWithEscape : public DS2480B {
+  public:
+    DS2480BWithEscape(Core::Sleep & sleep, Core::Uart & uart)
+        : DS2480B(sleep, uart) {}
+
+    Core::error_code escape();
+  };
+
+  class DS9400WithEscape : public DS9400 {
+  public:
+    explicit DS9400WithEscape(Core::Uart & uart) : DS9400(uart) {}
+
+    Core::error_code escape();
+  };
+
+  enum Bus { OneWire, I2C };
+
+  Core::SerialPort * serialPort;
+  Bus currentBus;
+  DS2480BWithEscape ds2480b;
+  OneWireMaster oneWireMaster_;
+  DS9400WithEscape ds9400;
+  I2CMaster i2cMaster_;
+
+  Core::error_code selectOneWire();
+  Core::error_code selectBus(Bus newBus);
+
+  friend class OneWireMaster;
+  friend class I2CMaster;
+};
+
+} // namespace MaximInterfaceDevices
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceMbed/I2CMaster.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 MaximInterfaceMbed {
+
+using namespace MaximInterfaceCore;
+
+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::doWritePacket(uint_least8_t address,
+                                    span<const uint_least8_t> data,
+                                    bool sendStop) {
+  return (i2c->write(address, reinterpret_cast<const char *>(data.data()),
+                     data.size(), !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::doReadPacket(uint_least8_t address,
+                                   span<uint_least8_t> data, bool sendStop) {
+  return (i2c->read(address, reinterpret_cast<char *>(data.data()), data.size(),
+                    !sendStop) == 0)
+             ? error_code()
+             : make_error_code(NackError);
+}
+
+} // namespace MaximInterfaceMbed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceMbed/I2CMaster.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 MaximInterfaceMbed_I2CMaster
+#define MaximInterfaceMbed_I2CMaster
+
+#include <MaximInterfaceCore/I2CMaster.hpp>
+#include <mbed-os/drivers/I2C.h>
+
+namespace MaximInterfaceMbed {
+
+/// Wrapper for mbed::I2C.
+class I2CMaster : public MaximInterfaceCore::I2CMaster {
+public:
+  explicit I2CMaster(mbed::I2C & i2c) : i2c(&i2c) {}
+
+  void setI2C(mbed::I2C & i2c) { this->i2c = &i2c; }
+
+  virtual MaximInterfaceCore::error_code start(uint_least8_t address);
+
+  virtual MaximInterfaceCore::error_code stop();
+
+  virtual MaximInterfaceCore::error_code writeByte(uint_least8_t data);
+
+  virtual MaximInterfaceCore::error_code readByte(AckStatus status,
+                                                  uint_least8_t & data);
+
+protected:
+  virtual MaximInterfaceCore::error_code
+  doReadPacket(uint_least8_t address,
+               MaximInterfaceCore::span<uint_least8_t> data, bool sendStop);
+
+  virtual MaximInterfaceCore::error_code
+  doWritePacket(uint_least8_t address,
+                MaximInterfaceCore::span<const uint_least8_t> data,
+                bool sendStop);
+
+private:
+  mbed::I2C * i2c;
+};
+
+} // namespace MaximInterfaceMbed
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceMbed/Sleep.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 <mbed-os/platform/mbed_wait_api.h>
+#include "Sleep.hpp"
+
+namespace MaximInterfaceMbed {
+
+void sleep(int ms) { wait_ms(ms); }
+
+Sleep & Sleep::instance() {
+  static Sleep instance;
+  return instance;
+}
+
+void Sleep::invoke(int ms) const { sleep(ms); }
+
+} // namespace MaximInterfaceMbed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceMbed/Sleep.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 MaximInterfaceMbed_Sleep
+#define MaximInterfaceMbed_Sleep
+
+#include <MaximInterfaceCore/Sleep.hpp>
+#include <MaximInterfaceCore/Uncopyable.hpp>
+
+namespace MaximInterfaceMbed {
+
+void sleep(int ms);
+
+class Sleep : public MaximInterfaceCore::Sleep,
+              private MaximInterfaceCore::Uncopyable {
+public:
+  static Sleep & instance();
+  virtual void invoke(int ms) const;
+
+private:
+  Sleep() {}
+};
+
+} // namespace MaximInterfaceMbed
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceMbed/Uart.cpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 <MaximInterfaceCore/Error.hpp>
+#include <mbed-os/drivers/Timer.h>
+#include "Uart.hpp"
+
+namespace MaximInterfaceMbed {
+
+using namespace MaximInterfaceCore;
+
+static const int timeout_ms = 10000;
+
+error_code Uart::setBaudRate(int_least32_t baudRate) {
+  serial->baud(baudRate);
+  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 MaximInterfaceMbed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceMbed/Uart.hpp	Mon Jul 22 11:44:07 2019 -0500
@@ -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 MaximInterfaceMbed_Uart
+#define MaximInterfaceMbed_Uart
+
+#include <MaximInterfaceCore/Uart.hpp>
+#include <mbed-os/drivers/Serial.h>
+
+namespace MaximInterfaceMbed {
+
+/// Wrapper for mbed::Serial.
+class Uart : public MaximInterfaceCore::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 MaximInterfaceCore::error_code setBaudRate(int_least32_t baudRate);
+
+  virtual MaximInterfaceCore::error_code sendBreak();
+
+  virtual MaximInterfaceCore::error_code clearReadBuffer();
+
+  virtual MaximInterfaceCore::error_code writeByte(uint_least8_t data);
+
+  virtual MaximInterfaceCore::error_code readByte(uint_least8_t & data);
+
+  static const MaximInterfaceCore::error_category & errorCategory();
+
+private:
+  mbed::Serial * serial;
+};
+
+inline MaximInterfaceCore::error_code make_error_code(Uart::ErrorValue e) {
+  return MaximInterfaceCore::error_code(e, Uart::errorCategory());
+}
+
+} // namespace MaximInterfaceMbed
+
+#endif
--- a/Platforms/mbed/I2CMaster.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*******************************************************************************
-* 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::writePacketImpl(uint_least8_t address,
-                                      span<const uint_least8_t> data,
-                                      bool sendStop) {
-  return (i2c->write(address, reinterpret_cast<const char *>(data.data()),
-                     data.size(), !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::readPacketImpl(uint_least8_t address,
-                                     span<uint_least8_t> data, bool sendStop) {
-  return (i2c->read(address, reinterpret_cast<char *>(data.data()), data.size(),
-                    !sendStop) == 0)
-             ? error_code()
-             : make_error_code(NackError);
-}
-
-} // namespace mbed
-} // namespace MaximInterface
--- a/Platforms/mbed/I2CMaster.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*******************************************************************************
-* 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 <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 readByte(AckStatus status, uint_least8_t & data);
-
-protected:
-  virtual error_code readPacketImpl(uint_least8_t address,
-                                    span<uint_least8_t> data, bool sendStop);
-                                    
-  virtual error_code writePacketImpl(uint_least8_t address,
-                                     span<const uint_least8_t> data,
-                                     bool sendStop);
-
-private:
-  ::mbed::I2C * i2c;
-};
-
-} // namespace mbed
-} // namespace MaximInterface
-
-#endif
--- a/Platforms/mbed/Sleep.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*******************************************************************************
-* 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::invoke(int ms) const { sleep(ms); }
-
-} // namespace mbed
-} // namespace MaximInterface
--- a/Platforms/mbed/Sleep.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*******************************************************************************
-* 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 invoke(int ms) const;
-
-private:
-  Sleep() {}
-};
-
-} // namespace mbed
-} // namespace MaximInterface
-
-#endif
--- a/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/GpioOneWireMaster.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,173 +0,0 @@
-/*******************************************************************************
-* 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 */
--- a/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/GpioOneWireMaster.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*******************************************************************************
-* 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
--- a/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_ARM_STD/owlink.s	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,209 +0,0 @@
-/******************************************************************//**
-* 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
-//
-// Make PROC_CLOCK_MHZ and OVERHEAD_TUNING divisible by PROC_CYCLES_PER_LOOP
-// for best results
-//
-// Processor clock in MHz
-#define PROC_CLOCK_MHZ (__SYSTEM_HFX / 1000000)
-//
-// Fraction where OverheadTime(us) = OVERHEAD_TUNING / PROC_CLOCK_MHZ
-#define OVERHEAD_TUNING 18
-//
-// ARM specifies 1-3 cycles for pipeline refill following a branch
-#define PIPELINE_REFILL_PROC_CYCLES 1
-
-// ow_usdelay constants
-#define PROC_CYCLES_PER_LOOP (2 + PIPELINE_REFILL_PROC_CYCLES)
-#define LOOPS_PER_US (PROC_CLOCK_MHZ / PROC_CYCLES_PER_LOOP)
-#define LOOPS_REMOVED_TUNING (OVERHEAD_TUNING / PROC_CYCLES_PER_LOOP)
-
-// OneWireTiming 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
-  
-// void write_ow_gpio_low(volatile uint32_t * portReg, unsigned int pinMask)
-  MACRO
-$label write_ow_gpio_low
-  ldr R2, [R0]
-  bic R2, R2, R1
-  str R2, [R0]
-  MEND
-  
-// void write_ow_gpio_high(volatile uint32_t * 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, const volatile uint32_t * inReg,
-//             volatile uint32_t * outReg, unsigned int pinMask,
-//             const OneWireTiming * 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: inReg
-  // R2: outReg
-  // R3: pinMask
-  // R4: tSLOT
-  // R5: tMSR
-  // R6: timing
-  // R7: Scratch
-  // R8: Scratch
-  // R14: Scratch
-  
-  // Reorganize registers for upcoming function calls
-  mov R8, R1 // inReg to R8
-  mov R7, R2 // outReg 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: outReg
-  // R8: inReg
-  // 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: outReg
-  // R8: inReg
-  // R14: Scratch
-  mov R0, R7 // outReg
-  write_ow_gpio_low // Pull low
-  mov R0, R6 // tLOW
-  bl ow_usdelay // Delay for tLOW
-  mov R0, R7 // outReg
-  write_ow_gpio_high // Release pin
-  mov R0, R5 // delay2
-  bl ow_usdelay // Delay for sample time
-  ldr R5, [R8] // Read *inReg
-  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: outReg
-  // R8: inReg
-  // R14: Scratch
-  mov R0, R7 // outReg
-  write_ow_gpio_low // Pull low
-  mov R0, R5 // tMSR
-  bl ow_usdelay // Delay for tMSR
-  ldr R5, [R8] // Read *inReg
-  mov R0, R6 // delay2
-  bl ow_usdelay // Delay for release
-  mov R0, R7 // outReg
-  write_ow_gpio_high // Release pin
-  // endif (*sendRecvBit & 1)
-  // R0: Scratch
-  // R1: pinMask
-  // R2: Scratch
-  // R3: sendRecvBit
-  // R4: tREC
-  // R5: *inReg
-  // R6: Scratch
-  // R7: outReg
-  // R8: inReg
-  // R14: Scratch
-  
-recovery_delay
-  mov R0, R4
-  bl ow_usdelay // Delay for tREC
-  
-  // Parse received bit
-  // *sendRecvBit = ((*inReg & 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
--- a/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_GCC_ARM/owlink.S	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,210 +0,0 @@
-/******************************************************************//**
-* 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
-//
-// Make PROC_CLOCK_MHZ and OVERHEAD_TUNING divisible by PROC_CYCLES_PER_LOOP
-// for best results
-//
-// Processor clock in MHz
-#define PROC_CLOCK_MHZ (__SYSTEM_HFX / 1000000)
-//
-// Fraction where OverheadTime(us) = OVERHEAD_TUNING / PROC_CLOCK_MHZ
-#define OVERHEAD_TUNING 18
-//
-// ARM specifies 1-3 cycles for pipeline refill following a branch
-#define PIPELINE_REFILL_PROC_CYCLES 1
-
-// ow_usdelay constants
-#define PROC_CYCLES_PER_LOOP (2 + PIPELINE_REFILL_PROC_CYCLES)
-#define LOOPS_PER_US (PROC_CLOCK_MHZ / PROC_CYCLES_PER_LOOP)
-#define LOOPS_REMOVED_TUNING (OVERHEAD_TUNING / PROC_CYCLES_PER_LOOP)
-
-// OneWireTiming 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
-  
-// void write_ow_gpio_low(volatile uint32_t * portReg, unsigned int pinMask)
-.macro write_ow_gpio_low
-  ldr R2, [R0]
-  bic R2, R2, R1
-  str R2, [R0]
-  .endm
-  
-// void write_ow_gpio_high(volatile uint32_t * 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, const volatile uint32_t * inReg,
-//             volatile uint32_t * outReg, unsigned int pinMask,
-//             const OneWireTiming * 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: inReg
-  // R2: outReg
-  // R3: pinMask
-  // R4: tSLOT
-  // R5: tMSR
-  // R6: timing
-  // R7: Scratch
-  // R8: Scratch
-  // R14: Scratch
-  
-  // Reorganize registers for upcoming function calls
-  mov R8, R1 // inReg to R8
-  mov R7, R2 // outReg 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: outReg
-  // R8: inReg
-  // 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: outReg
-  // R8: inReg
-  // R14: Scratch
-  mov R0, R7 // outReg
-  write_ow_gpio_low // Pull low
-  mov R0, R6 // tLOW
-  bl ow_usdelay // Delay for tLOW
-  mov R0, R7 // outReg
-  write_ow_gpio_high // Release pin
-  mov R0, R5 // delay2
-  bl ow_usdelay // Delay for sample time
-  ldr R5, [R8] // Read *inReg
-  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: outReg
-  // R8: inReg
-  // R14: Scratch
-  mov R0, R7 // outReg
-  write_ow_gpio_low // Pull low
-  mov R0, R5 // tMSR
-  bl ow_usdelay // Delay for tMSR
-  ldr R5, [R8] // Read *inReg
-  mov R0, R6 // delay2
-  bl ow_usdelay // Delay for release
-  mov R0, R7 // outReg
-  write_ow_gpio_high // Release pin
-  // endif (*sendRecvBit & 1)
-  // R0: Scratch
-  // R1: pinMask
-  // R2: Scratch
-  // R3: sendRecvBit
-  // R4: tREC
-  // R5: *inReg
-  // R6: Scratch
-  // R7: outReg
-  // R8: inReg
-  // R14: Scratch
-  
-recovery_delay:
-  mov R0, R4
-  bl ow_usdelay // Delay for tREC
-  
-  // Parse received bit
-  // *sendRecvBit = ((*inReg & 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
--- a/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_IAR/owlink.s	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,207 +0,0 @@
-/******************************************************************//**
-* 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
-//
-// Make PROC_CLOCK_MHZ and OVERHEAD_TUNING divisible by PROC_CYCLES_PER_LOOP
-// for best results
-//
-// Processor clock in MHz
-#define PROC_CLOCK_MHZ (__SYSTEM_HFX / 1000000)
-//
-// Fraction where OverheadTime(us) = OVERHEAD_TUNING / PROC_CLOCK_MHZ
-#define OVERHEAD_TUNING 18
-//
-// ARM specifies 1-3 cycles for pipeline refill following a branch
-#define PIPELINE_REFILL_PROC_CYCLES 1
-
-// ow_usdelay constants
-#define PROC_CYCLES_PER_LOOP (2 + PIPELINE_REFILL_PROC_CYCLES)
-#define LOOPS_PER_US (PROC_CLOCK_MHZ / PROC_CYCLES_PER_LOOP)
-#define LOOPS_REMOVED_TUNING (OVERHEAD_TUNING / PROC_CYCLES_PER_LOOP)
-
-// OneWireTiming 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
-  
-// void write_ow_gpio_low(volatile uint32_t * portReg, unsigned int pinMask)
-write_ow_gpio_low MACRO
-  ldr R2, [R0]
-  bic R2, R2, R1
-  str R2, [R0]
-  ENDM
-  
-// void write_ow_gpio_high(volatile uint32_t * 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, const volatile uint32_t * inReg,
-//             volatile uint32_t * outReg, unsigned int pinMask,
-//             const OneWireTiming * 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: inReg
-  // R2: outReg
-  // R3: pinMask
-  // R4: tSLOT
-  // R5: tMSR
-  // R6: timing
-  // R7: Scratch
-  // R8: Scratch
-  // R14: Scratch
-  
-  // Reorganize registers for upcoming function calls
-  mov R8, R1 // inReg to R8
-  mov R7, R2 // outReg 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: outReg
-  // R8: inReg
-  // 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: outReg
-  // R8: inReg
-  // R14: Scratch
-  mov R0, R7 // outReg
-  write_ow_gpio_low // Pull low
-  mov R0, R6 // tLOW
-  bl ow_usdelay // Delay for tLOW
-  mov R0, R7 // outReg
-  write_ow_gpio_high // Release pin
-  mov R0, R5 // delay2
-  bl ow_usdelay // Delay for sample time
-  ldr R5, [R8] // Read *inReg
-  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: outReg
-  // R8: inReg
-  // R14: Scratch
-  mov R0, R7 // outReg
-  write_ow_gpio_low // Pull low
-  mov R0, R5 // tMSR
-  bl ow_usdelay // Delay for tMSR
-  ldr R5, [R8] // Read *inReg
-  mov R0, R6 // delay2
-  bl ow_usdelay // Delay for release
-  mov R0, R7 // outReg
-  write_ow_gpio_high // Release pin
-  // endif (*sendRecvBit & 1)
-  // R0: Scratch
-  // R1: pinMask
-  // R2: Scratch
-  // R3: sendRecvBit
-  // R4: tREC
-  // R5: *inReg
-  // R6: Scratch
-  // R7: outReg
-  // R8: inReg
-  // R14: Scratch
-  
-recovery_delay
-  mov R0, R4
-  bl ow_usdelay // Delay for tREC
-  
-  // Parse received bit
-  // *sendRecvBit = ((*inReg & 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
--- a/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/owlink.h	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*******************************************************************************
-* 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 in 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);
-
-/// @brief Send and receive one bit, 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[in] inReg Input register for GPIO pin.
-/// @param[in,out] 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, const volatile uint32_t * inReg,
-            volatile uint32_t * outReg, unsigned int pinMask,
-            const OneWireTiming * timing);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* MaximInterface_owlink */
--- a/Platforms/mbed/Uart.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*******************************************************************************
-* 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::setBaudRate(int_least32_t baudRate) {
-  serial->baud(baudRate);
-  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
--- a/Platforms/mbed/Uart.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*******************************************************************************
-* 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 <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 setBaudRate(int_least32_t baudRate);
-  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
--- a/Utilities/Algorithm.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2018 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_Algorithm
-#define MaximInterface_Algorithm
-
-/// Alternative to std::max when a constant expression is required.
-#define MaximInterface_MAX(a, b) ((a) < (b) ? (b) : (a))
-
-/// Alternative to std::min when a constant expression is required.
-#define MaximInterface_MIN(a, b) ((b) < (a) ? (b) : (a))
-
-#endif
--- a/Utilities/ChangeSizeType.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*******************************************************************************
-* 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_ChangeSizeType
-#define MaximInterface_ChangeSizeType
-
-#include <stdint.h>
-#include <algorithm>
-#include <limits>
-#include "span.hpp"
-#include "system_error.hpp"
-
-namespace MaximInterface {
-
-/// @brief
-/// Adapts functions taking an array pointer and size where the size type is
-/// nonstandard.
-/// @tparam NewSize Nonstandard size type.
-/// @tparam Func Must be callable as func(Data *, NewSize).
-/// @tparam Data Array element type.
-/// @param func Callback for processing chunks of data.
-/// @param data Data to process with callback.
-template <typename NewSize, typename Func, typename Data>
-error_code changeSizeType(Func func, span<Data> data) {
-  using namespace std;
-  typedef typename span<Data>::index_type DataSize;
-
-  error_code result;
-  // Check if NewSize can represent the maximum value of DataSize.
-  if (static_cast<uintmax_t>(numeric_limits<DataSize>::max()) >
-      static_cast<uintmax_t>(numeric_limits<NewSize>::max())) {
-    DataSize dataIdx = 0;
-    do {
-      const span<Data> chunk =
-          data.subspan(dataIdx, min<DataSize>(data.size() - dataIdx,
-                                              numeric_limits<NewSize>::max()));
-      result = func(chunk.data(), static_cast<NewSize>(chunk.size()));
-      dataIdx += chunk.size();
-    } while (dataIdx < data.size() && !result);
-  } else {
-    result = func(data.data(), static_cast<NewSize>(data.size()));
-  }
-  return result;
-}
-
-} // namespace MaximInterface
-
-#endif
\ No newline at end of file
--- a/Utilities/Ecc256.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*******************************************************************************
-* 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 "Ecc256.hpp"
-
-namespace MaximInterface {
-namespace Ecc256 {
-
-void copy(Point::const_span src, Point::span dst) {
-  copy(src.x, dst.x);
-  copy(src.y, dst.y);
-}
-
-void copy(KeyPair::const_span src, KeyPair::span dst) {
-  copy(src.privateKey, dst.privateKey);
-  copy(src.publicKey, dst.publicKey);
-}
-
-void copy(Signature::const_span src, Signature::span dst) {
-  copy(src.r, dst.r);
-  copy(src.s, dst.s);
-}
-
-PublicKey::span CertificateData::publicKey() {
-  const PublicKey::span span = {
-      make_span(result_).subspan<publicKeyIdx, Scalar::size>(),
-      make_span(result_)
-          .subspan<publicKeyIdx + Scalar::size, Scalar::size>()};
-  return span;
-}
-
-} // namespace Ecc256
-} // namespace MaximInterface
--- a/Utilities/Ecc256.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,249 +0,0 @@
-/*******************************************************************************
-* 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_span.hpp"
-#include "Export.h"
-#include "ManId.hpp"
-#include "RomId.hpp"
-
-namespace MaximInterface {
-namespace Ecc256 {
-
-typedef array_span<uint_least8_t, 32> Scalar;
-
-struct Point {
-  struct const_span {
-    Scalar::const_span x;
-    Scalar::const_span y;
-  };
-
-  struct span {
-    Scalar::span x;
-    Scalar::span y;
-
-    operator const_span() const {
-      const const_span sp = {x, y};
-      return sp;
-    }
-  };
-
-  struct array {
-    Scalar::array x;
-    Scalar::array y;
-
-    operator span() {
-      const span sp = {x, y};
-      return sp;
-    }
-    
-    operator const_span() const {
-      const const_span sp = {x, y};
-      return sp;
-    }
-  };
-  
-private:
-  Point(); // deleted
-};
-
-MaximInterface_EXPORT void copy(Point::const_span src, Point::span dst);
-
-typedef Scalar PrivateKey;
-typedef Point PublicKey;
-
-struct KeyPair {
-  struct const_span {
-    PrivateKey::const_span privateKey;
-    PublicKey::const_span publicKey;
-  };
-
-  struct span {
-    PrivateKey::span privateKey;
-    PublicKey::span publicKey;
-
-    operator const_span() const {
-      const const_span sp = {privateKey, publicKey};
-      return sp;
-    }
-  };
-
-  struct array {
-    PrivateKey::array privateKey;
-    PublicKey::array publicKey;
-
-    operator span() {
-      const span sp = {privateKey, publicKey};
-      return sp;
-    }
-    
-    operator const_span() const {
-      const const_span sp = {privateKey, publicKey};
-      return sp;
-    }
-  };
-  
-private:
-  KeyPair(); // deleted
-};
-
-MaximInterface_EXPORT void copy(KeyPair::const_span src, KeyPair::span dst);
-
-struct Signature {
-  struct const_span {
-    Scalar::const_span r;
-    Scalar::const_span s;
-  };
-
-  struct span {
-    Scalar::span r;
-    Scalar::span s;
-
-    operator const_span() const {
-      const const_span sp = {r, s};
-      return sp;
-    }
-  };
-
-  struct array {
-    Scalar::array r;
-    Scalar::array s;
-
-    operator span() {
-      const span sp = {r, s};
-      return sp;
-    }
-    
-    operator const_span() const {
-      const const_span sp = {r, s};
-      return sp;
-    }
-  };
-  
-private:
-  Signature(); // deleted
-};
-
-MaximInterface_EXPORT void copy(Signature::const_span src, Signature::span dst);
-
-/// Data used to create a device key certificate for ECC-256 authenticators.
-class CertificateData {
-public:
-  typedef array_span<uint_least8_t, 2 * Scalar::size + RomId::size + ManId::size>
-      Result;
-
-  CertificateData() : result_() {}
-
-  /// Formatted data result.
-  Result::const_span result() const { return result_; }
-
-  /// @name Public Key
-  /// @brief Public key of the device.
-  /// @{
-  
-  /// Get mutable Public Key.
-  MaximInterface_EXPORT PublicKey::span publicKey();
-  
-  /// Get immutable Public Key.
-  PublicKey::const_span publicKey() const {
-    return const_cast<CertificateData &>(*this).publicKey();
-  }
-  
-  /// Set Public Key.
-  CertificateData & setPublicKey(PublicKey::const_span publicKey) {
-    copy(publicKey, this->publicKey());
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name ROM ID
-  /// @brief 1-Wire ROM ID of the device.
-  /// @{
-  
-  /// Get mutable ROM ID.
-  RomId::span romId() {
-    return make_span(result_).subspan<romIdIdx, RomId::size>();
-  }
-  
-  /// Get immutable ROM ID.
-  RomId::const_span romId() const {
-    return const_cast<CertificateData &>(*this).romId();
-  }
-  
-  /// Set ROM ID.
-  CertificateData & setRomId(RomId::const_span romId) {
-    copy(romId, this->romId());
-    return *this;
-  }
-  
-  /// @}
-
-  /// @name MAN ID
-  /// @brief Manufacturer ID of the device.
-  /// @{
-  
-  /// Get mutable MAN ID.
-  ManId::span manId() {
-    return make_span(result_).subspan<manIdIdx, ManId::size>();
-  }
-  
-  /// Get immutable MAN ID.
-  ManId::const_span manId() const {
-    return const_cast<CertificateData &>(*this).manId();
-  }
-  
-  /// Set MAN ID.
-  CertificateData & setManId(ManId::const_span manId) {
-    copy(manId, this->manId());
-    return *this;
-  }
-  
-  /// @}
-
-private:
-  typedef Result::span::index_type index;
-
-  static const index publicKeyIdx = 0;
-  static const index romIdIdx = publicKeyIdx + 2 * Scalar::size;
-  static const index manIdIdx = romIdIdx + RomId::size;
-
-  Result::array result_;
-};
-
-} // namespace Ecc256
-} // namespace MaximInterface
-
-#endif
--- a/Utilities/Error.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*******************************************************************************
-* 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
--- a/Utilities/Error.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*******************************************************************************
-* 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 {
-
-/// @brief Get the default error message associated with a condition.
-/// @details Typically used by an error_category when the condition is unknown.
-MaximInterface_EXPORT const char * defaultErrorMessage(int condition);
-
-}
-
-#endif
--- a/Utilities/Export.h	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*******************************************************************************
-* 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
-  #if defined(_MSC_VER) && defined(MaximInterface_EXPORTING)
-    #define MaximInterface_EXPORT __declspec(dllexport)
-  #else
-    #define MaximInterface_EXPORT
-  #endif
-#endif
--- a/Utilities/FlagSet.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,226 +0,0 @@
-/*******************************************************************************
-* 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 {
-
-/// @brief
-/// 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); }
-
-  /// @name 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(); }
-  
-  /// @}
-
-  /// @name Capacity
-  /// @{
-  
-  size_t size() const { return bits.size(); }
-  
-  /// @}
-
-  /// @name 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;
-  }
-  
-  /// @}
-
-  /// @name 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
--- a/Utilities/Function.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,565 +0,0 @@
-/*******************************************************************************
-* 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 "SafeBool.hpp"
-#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 aligner1;
-  long int aligner2;
-  void * aligner3;
-};
-
-// 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-3 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 SafeBool() const {
-    return makeSafeBool(callableWrapper.target() != NULL);
-  }
-
-  ResultType operator()() const {
-    return callableWrapper.target() ? callableWrapper.target()->invoke()
-                                    : ResultType();
-  }
-
-private:
-  class Callable {
-  public:
-    virtual ~Callable() {}
-    virtual ResultType invoke() 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 invoke() 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 SafeBool() const {
-    return makeSafeBool(callableWrapper.target() != NULL);
-  }
-
-  ResultType operator()(ArgumentType arg) const {
-    return callableWrapper.target() ? callableWrapper.target()->invoke(arg)
-                                    : ResultType();
-  }
-
-private:
-  class Callable {
-  public:
-    virtual ~Callable() {}
-    virtual ResultType invoke(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 invoke(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 SafeBool() const {
-    return makeSafeBool(callableWrapper.target() != NULL);
-  }
-
-  ResultType operator()(FirstArgumentType arg1, SecondArgumentType arg2) const {
-    return callableWrapper.target()
-               ? callableWrapper.target()->invoke(arg1, arg2)
-               : ResultType();
-  }
-
-private:
-  class Callable {
-  public:
-    virtual ~Callable() {}
-    virtual ResultType invoke(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 invoke(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);
-}
-
-// Function implementation for three argument functions.
-template <typename FirstArgumentType, typename SecondArgumentType,
-          typename ThirdArgumentType, typename ResultType>
-class Function<ResultType(FirstArgumentType, SecondArgumentType,
-                          ThirdArgumentType)> {
-public:
-  typedef ResultType result_type;
-
-  Function(ResultType (*func)(FirstArgumentType, SecondArgumentType,
-                              ThirdArgumentType) = NULL)
-      : callableWrapper() {
-    if (func) {
-      callableWrapper = func;
-    }
-  }
-
-  template <typename F> Function(F func) : callableWrapper(func) {}
-
-  const Function & operator=(ResultType (*func)(FirstArgumentType,
-                                                SecondArgumentType,
-                                                ThirdArgumentType)) {
-    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 SafeBool() const {
-    return makeSafeBool(callableWrapper.target() != NULL);
-  }
-
-  ResultType operator()(FirstArgumentType arg1, SecondArgumentType arg2,
-                        ThirdArgumentType arg3) const {
-    return callableWrapper.target()
-               ? callableWrapper.target()->invoke(arg1, arg2, arg3)
-               : ResultType();
-  }
-
-private:
-  class Callable {
-  public:
-    virtual ~Callable() {}
-    virtual ResultType invoke(FirstArgumentType, SecondArgumentType,
-                              ThirdArgumentType) 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 invoke(FirstArgumentType arg1, SecondArgumentType arg2,
-                              ThirdArgumentType arg3) const {
-      return func(arg1, arg2, arg3);
-    }
-
-    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 ThirdArgumentType, typename ResultType>
-inline void swap(Function<ResultType(FirstArgumentType, SecondArgumentType,
-                                     ThirdArgumentType)> & lhs,
-                 Function<ResultType(FirstArgumentType, SecondArgumentType,
-                                     ThirdArgumentType)> & rhs) {
-  lhs.swap(rhs);
-}
-
-} // namespace MaximInterface
-
-#endif
--- a/Utilities/HexConversions.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*******************************************************************************
-* 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 <cctype>
-#include <cstdio>
-#include <cstdlib>
-#include "HexConversions.hpp"
-
-using std::string;
-using std::vector;
-
-namespace MaximInterface {
-
-static const int charsPerByte = 2;
-
-string byteArrayToHexString(span<const uint_least8_t> byteArray) {
-  string hexString;
-  hexString.reserve(byteArray.size() * charsPerByte);
-  for (span<const uint_least8_t>::index_type i = 0; i < byteArray.size(); ++i) {
-    char hexBuf[charsPerByte + 1];
-    std::sprintf(hexBuf, "%2.2X", byteArray[i] & 0xFF);
-    hexString.append(hexBuf, charsPerByte);
-  }
-  return hexString;
-}
-
-optional<vector<uint_least8_t> >
-hexStringToByteArray(const string & hexString) {
-  optional<vector<uint_least8_t> > byteArray = vector<uint_least8_t>();
-  byteArray->reserve(hexString.size() / charsPerByte);
-  char hexBuf[charsPerByte + 1];
-  char * const hexBufEnd = hexBuf + charsPerByte;
-  *hexBufEnd = '\0';
-  char * hexBufIt = hexBuf;
-  for (string::const_iterator hexStringIt = hexString.begin(),
-                              hexStringEnd = hexString.end();
-       hexStringIt != hexStringEnd; ++hexStringIt) {
-    if (!std::isspace(*hexStringIt)) {
-      *hexBufIt = *hexStringIt;
-      if (++hexBufIt == hexBufEnd) {
-        char * hexBufParseEnd;
-        byteArray->push_back(static_cast<uint_least8_t>(
-            std::strtoul(hexBuf, &hexBufParseEnd, 16)));
-        if (hexBufParseEnd != hexBufEnd) {
-          break;
-        }
-        hexBufIt = hexBuf;
-      }
-    }
-  }
-  if (hexBufIt != hexBuf) {
-    byteArray.reset();
-  }
-  return byteArray;
-}
-
-} // namespace MaximInterface
--- a/Utilities/HexConversions.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*******************************************************************************
-* 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 "Export.h"
-#include "optional.hpp"
-#include "span.hpp"
-
-namespace MaximInterface {
-
-/// Convert a byte array to a hex string.
-MaximInterface_EXPORT std::string
-byteArrayToHexString(span<const uint_least8_t> byteArray);
-
-/// Convert a hex string to a byte array.
-MaximInterface_EXPORT optional<std::vector<uint_least8_t> >
-hexStringToByteArray(const std::string & hexString);
-
-} // namespace MaximInterface
-
-#endif
--- a/Utilities/ManId.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*******************************************************************************
-* 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_span.hpp"
-
-namespace MaximInterface {
-
-/// Standard container for a manufacturer ID.
-typedef array_span<uint_least8_t, 2> ManId;
-
-} // namespace MaximInterface
-
-#endif
--- a/Utilities/RomId.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*******************************************************************************
-* 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_span.hpp"
-#include "crc.hpp"
-
-namespace MaximInterface {
-
-/// Standard container for a 1-Wire ROM ID.
-typedef array_span<uint_least8_t, 8> RomId;
-
-/// @name Family Code
-/// @{
-
-/// Get the Family Code byte.
-inline RomId::element familyCode(RomId::const_span romId) {
-  return romId[0];
-}
-
-/// Set the Family Code byte.
-inline void setFamilyCode(RomId::span romId, RomId::element familyCode) {
-  romId[0] = familyCode;
-}
-
-/// @}
-
-/// @name CRC8
-/// @{
-
-/// Get the CRC8 byte.
-inline RomId::element crc8(RomId::const_span romId) { 
-  return *romId.last<1>().data();
-}
-
-/// Set the CRC8 byte.
-inline void setCrc8(RomId::span romId, RomId::element crc8) {
-  *romId.last<1>().data() = crc8;
-}
-
-/// @}
-
-/// @brief 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(RomId::const_span romId) {
-  return calculateCrc8(romId.first(romId.size() - 1)) == crc8(romId);
-}
-
-} // namespace MaximInterface
-
-#endif
--- a/Utilities/SafeBool.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2018 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_SafeBool
-#define MaximInterface_SafeBool
-
-#include <stddef.h>
-
-namespace MaximInterface {
-namespace detail {
-
-// Implement SafeBool as a member function pointer since some compilers allow
-// function pointer to void pointer conversion.
-struct SafeBoolHelper {
-  void trueValue() const {}
-  
-private:
-  SafeBoolHelper(); // deleted
-};
-
-} // namespace detail
-
-/// @brief Type definition for SafeBool.
-/// @details
-/// SafeBool is a boolean type that eliminates many error-prone implicit
-/// conversions allowed by the fundamental bool type.
-/// @note
-/// SafeBool can be used to add an explicit bool conversion operator to a type.
-typedef void (detail::SafeBoolHelper::*SafeBool)() const;
-
-/// Constructor for SafeBool.
-inline SafeBool makeSafeBool(bool value) {
-  return value ? &detail::SafeBoolHelper::trueValue : NULL;
-}
-
-} // namespace MaximInterface
-
-#endif
--- a/Utilities/Segment.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*******************************************************************************
-* 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 {
-
-/// @brief
-/// Advances a given iterator by a given number of elements with bounds checking.
-/// @tparam 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;
-}
-
-/// @brief Locates an iterator sub-range using segment number addressing.
-/// @details
-/// Useful for devices that divide the memory space into uniform chunks such as
-/// pages and segments.
-/// @tparam 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 iterator 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
--- a/Utilities/Sha256.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*******************************************************************************
-* 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_span.hpp"
-
-namespace MaximInterface {
-namespace Sha256 {
-
-/// Container for a SHA-256 hash.
-typedef array_span<uint_least8_t, 32> Hash;
-
-/// @brief Data for Compute Write MAC operation.
-/// @details
-/// Used by SHA-256 MAC authenticators including DS28E15/22/25 and DS2465.
-typedef array_span<uint_least8_t, 20> WriteMacData;
-
-/// @brief Data for the Compute Auth. MAC and Compute Slave Secret operations.
-/// @copydetails WriteMacData
-typedef array_span<uint_least8_t, 76> AuthenticationData;
-
-} // namespace Sha256
-} // namespace MaximInterface
-
-#endif
--- a/Utilities/Uncopyable.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*******************************************************************************
-* 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
--- a/Utilities/WriteMessage.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*******************************************************************************
-* 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
--- a/Utilities/array.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,191 +0,0 @@
-/*******************************************************************************
-* 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;
-
-  /// @name 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 data()[pos]; }
-  
-  reference front() {
-    return const_cast<reference>(static_cast<const array &>(*this).front());
-  }
-  
-  const_reference front() const { return operator[](0); }
-  
-  reference back() {
-    return const_cast<reference>(static_cast<const array &>(*this).back());
-  }
-  
-  const_reference back() const { return operator[](size() - 1); }
-  
-  pointer data() {
-    return const_cast<pointer>(static_cast<const array &>(*this).data());
-  }
-  
-  const_pointer data() const { return _buffer; }
-  
-  /// @}
-
-  /// @name Iterators
-  /// @{
-  
-  iterator begin() {
-    return const_cast<iterator>(static_cast<const array &>(*this).cbegin());
-  }
-  
-  const_iterator begin() const { return cbegin(); }
-  
-  const_iterator cbegin() const { return data(); }
-  
-  iterator end() {
-    return const_cast<iterator>(static_cast<const array &>(*this).cend());
-  }
-  
-  const_iterator end() const { return cend(); }
-  
-  const_iterator cend() const { return cbegin() + 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(); }
-  
-  /// @}
-
-  /// @name Capacity
-  /// @{
-  
-  static bool empty() { return size() == 0; }
-  
-  static size_type size() { return N; }
-  
-  static size_type max_size() { return size(); }
-  
-  /// Alternative to size() when a constant expression is required.
-  static const size_type csize = N;
-  
-  /// @}
-
-  /// @name Operations
-  /// @{
-  
-  void fill(const_reference value) { std::fill(begin(), end(), value); }
-  
-  void swap(array & other) { std::swap_ranges(begin(), end(), other.begin()); }
-  
-  /// @}
-
-  /// @private
-  /// @note Implementation detail set public to allow aggregate initialization.
-  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
--- a/Utilities/array_span.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2018 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_span
-#define MaximInterface_array_span
-
-#include "array.hpp"
-#include "span.hpp"
-#include "type_traits.hpp"
-
-namespace MaximInterface {
-
-/// @brief
-/// Defines a standard set of types for data fields that are represented as a
-/// fixed-size array of elements.
-/// @tparam T A const qualifier is not allowed.
-template <typename T, size_t N> struct array_span {
-  typedef typename remove_volatile<T>::type element;
-  static const size_t size = N;
-  
-  typedef MaximInterface::array<element, N> array;
-  typedef MaximInterface::span<const T, N> const_span;
-  typedef MaximInterface::span<T, N> span;
-  
-private:
-  array_span(); // deleted
-};
-
-// Specialization for "const T" is not defined.
-template <typename T, size_t N> struct array_span<const T, N>;
-
-}
-
-#endif
--- a/Utilities/crc.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*******************************************************************************
-* 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(span<const uint_least8_t> data, uint_fast8_t crc) {
-  for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++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(span<const uint_least8_t> data,
-                             uint_fast16_t crc) {
-  for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) {
-    crc = calculateCrc16(data[i], crc);
-  }
-  return crc;
-}
-
-} // namespace MaximInterface
--- a/Utilities/crc.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*******************************************************************************
-* 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>
-#include "span.hpp"
-
-namespace MaximInterface {
-
-/// @brief 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);
-
-/// @brief Perform a CRC8 calculation with variable length data.
-/// @param[in] data Data array to pass through the CRC generator.
-/// @param crc Beginning state of the CRC generator.
-/// @returns The calculated CRC8.
-MaximInterface_EXPORT uint_fast8_t calculateCrc8(span<const uint_least8_t> data,
-                                                 uint_fast8_t crc = 0);
-
-/// @brief 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);
-
-/// @brief Perform a CRC16 calculation with variable length data.
-/// @param[in] data Data array to pass through the CRC generator.
-/// @param crc Beginning state of the CRC generator.
-/// @returns The calculated CRC16.
-MaximInterface_EXPORT uint_fast16_t
-calculateCrc16(span<const uint_least8_t> data, uint_fast16_t crc = 0);
-
-} // namespace MaximInterface
-
-#endif
--- a/Utilities/optional.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,318 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2018 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_optional
-#define MaximInterface_optional
-
-#include "SafeBool.hpp"
-
-// Include for std::swap.
-#include <algorithm>
-#include <utility>
-
-namespace MaximInterface {
-
-struct nullopt_t {
-  explicit nullopt_t(int) {}
-};
-
-static const nullopt_t nullopt(0);
-
-/// @brief Optional value container similar to std::optional.
-/// @details
-/// To prevent the need for aligned storage, this implementation imposes that
-/// types must be DefaultConstructible, CopyConstructible, and CopyAssignable.
-/// No exceptions are thrown when accessing a valueless optional.
-template <typename T> class optional {
-public:
-  typedef T value_type;
-
-  optional() : value_(), has_value_(false) {}
-  
-  optional(nullopt_t) : value_(), has_value_(false) {}
-
-  optional(const T & value) : value_(value), has_value_(true) {}
-
-  template <typename U>
-  explicit optional(const optional<U> & other)
-      : value_(other.value_), has_value_(other.has_value_) {}
-
-  optional & operator=(nullopt_t) {
-    reset();
-    return *this;
-  }
-
-  optional & operator=(const T & value) {
-    value_ = value;
-    has_value_ = true;
-    return *this;
-  }
-
-  template <typename U> optional & operator=(const optional<U> & other) {
-    if (has_value_ || other.has_value_) {
-      value_ = other.value_;
-      has_value_ = other.has_value_;
-    }
-    return *this;
-  }
-
-  bool has_value() const { return has_value_; }
-  
-  operator SafeBool() const { return makeSafeBool(has_value()); }
-
-  const T & value() const { return value_; }
-  
-  T & value() {
-    return const_cast<T &>(static_cast<const optional &>(*this).value());
-  }
-  
-  const T & operator*() const { return value(); }
-  
-  T & operator*() {
-    return const_cast<T &>(static_cast<const optional &>(*this).operator*());
-  }
-  
-  const T * operator->() const { return &value(); }
-  
-  T * operator->() {
-    return const_cast<T *>(static_cast<const optional &>(*this).operator->());
-  }
-
-  const T & value_or(const T & default_value) const {
-    return has_value() ? value() : default_value;
-  }
-
-  void swap(optional & other) {
-    if (has_value_ || other.has_value_) {
-      using std::swap;
-      swap(value_, other.value_);
-      swap(has_value_, other.has_value_);
-    }
-  }
-
-  void reset() {
-    if (has_value_) {
-      has_value_ = false;
-      value_ = T();
-    }
-  }
-
-private:
-  T value_;
-  bool has_value_;
-};
-
-template <typename T> optional<T> make_optional(const T & value) {
-  return value;
-}
-
-template <typename T> void swap(optional<T> & lhs, optional<T> & rhs) {
-  lhs.swap(rhs);
-}
-
-template <typename T, typename U>
-bool operator==(const optional<T> & lhs, const optional<U> & rhs) {
-  if (lhs.has_value() != rhs.has_value()) {
-    return false;
-  }
-  if (!lhs.has_value()) {
-    return true;
-  }
-  return lhs.value() == rhs.value();
-}
-
-template <typename T, typename U>
-bool operator!=(const optional<T> & lhs, const optional<U> & rhs) {
-  if (lhs.has_value() != rhs.has_value()) {
-    return true;
-  }
-  if (!lhs.has_value()) {
-    return false;
-  }
-  return lhs.value() != rhs.value();
-}
-
-template <typename T, typename U>
-bool operator<(const optional<T> & lhs, const optional<U> & rhs) {
-  if (!rhs.has_value()) {
-    return false;
-  }
-  if (!lhs.has_value()) {
-    return true;
-  }
-  return lhs.value() < rhs.value();
-}
-
-template <typename T, typename U>
-bool operator<=(const optional<T> & lhs, const optional<U> & rhs) {
-  if (!lhs.has_value()) {
-    return true;
-  }
-  if (!rhs.has_value()) {
-    return false;
-  }
-  return lhs.value() <= rhs.value();
-}
-
-template <typename T, typename U>
-bool operator>(const optional<T> & lhs, const optional<U> & rhs) {
-  if (!lhs.has_value()) {
-    return false;
-  }
-  if (!rhs.has_value()) {
-    return true;
-  }
-  return lhs.value() > rhs.value();
-}
-
-template <typename T, typename U>
-bool operator>=(const optional<T> & lhs, const optional<U> & rhs) {
-  if (!rhs.has_value()) {
-    return true;
-  }
-  if (!lhs.has_value()) {
-    return false;
-  }
-  return lhs.value() >= rhs.value();
-}
-
-template <typename T> bool operator==(const optional<T> & opt, nullopt_t) {
-  return !opt.has_value();
-}
-
-template <typename T> bool operator==(nullopt_t, const optional<T> & opt) {
-  return operator==(opt, nullopt);
-}
-
-template <typename T> bool operator!=(const optional<T> & opt, nullopt_t) {
-  return !operator==(opt, nullopt);
-}
-
-template <typename T> bool operator!=(nullopt_t, const optional<T> & opt) {
-  return operator!=(opt, nullopt);
-}
-
-template <typename T> bool operator<(const optional<T> &, nullopt_t) {
-  return false;
-}
-
-template <typename T> bool operator<(nullopt_t, const optional<T> & opt) {
-  return opt.has_value();
-}
-
-template <typename T> bool operator<=(const optional<T> & opt, nullopt_t) {
-  return !operator>(opt, nullopt);
-}
-
-template <typename T> bool operator<=(nullopt_t, const optional<T> & opt) {
-  return !operator>(nullopt, opt);
-}
-
-template <typename T> bool operator>(const optional<T> & opt, nullopt_t) {
-  return operator<(nullopt, opt);
-}
-
-template <typename T> bool operator>(nullopt_t, const optional<T> & opt) {
-  return operator<(opt, nullopt);
-}
-
-template <typename T> bool operator>=(const optional<T> & opt, nullopt_t) {
-  return !operator<(opt, nullopt);
-}
-
-template <typename T> bool operator>=(nullopt_t, const optional<T> & opt) {
-  return !operator<(nullopt, opt);
-}
-
-template <typename T, typename U>
-bool operator==(const optional<T> & opt, const U & value) {
-  return opt.has_value() ? opt.value() == value : false;
-}
-
-template <typename T, typename U>
-bool operator==(const T & value, const optional<U> & opt) {
-  return operator==(opt, value);
-}
-
-template <typename T, typename U>
-bool operator!=(const optional<T> & opt, const U & value) {
-  return opt.has_value() ? opt.value() != value : true;
-}
-
-template <typename T, typename U>
-bool operator!=(const T & value, const optional<U> & opt) {
-  return operator!=(opt, value);
-}
-
-template <typename T, typename U>
-bool operator<(const optional<T> & opt, const U & value) {
-  return opt.has_value() ? opt.value() < value : true;
-}
-
-template <typename T, typename U>
-bool operator<(const T & value, const optional<U> & opt) {
-  return opt.has_value() ? value < opt.value() : false;
-}
-
-template <typename T, typename U>
-bool operator<=(const optional<T> & opt, const U & value) {
-  return opt.has_value() ? opt.value() <= value : true;
-}
-
-template <typename T, typename U>
-bool operator<=(const T & value, const optional<U> & opt) {
-  return opt.has_value() ? value <= opt.value() : false;
-}
-
-template <typename T, typename U>
-bool operator>(const optional<T> & opt, const U & value) {
-  return opt.has_value() ? opt.value() > value : false;
-}
-
-template <typename T, typename U>
-bool operator>(const T & value, const optional<U> & opt) {
-  return opt.has_value() ? value > opt.value() : true;
-}
-
-template <typename T, typename U>
-bool operator>=(const optional<T> & opt, const U & value) {
-  return opt.has_value() ? opt.value() >= value : false;
-}
-
-template <typename T, typename U>
-bool operator>=(const T & value, const optional<U> & opt) {
-  return opt.has_value() ? value >= opt.value() : true;
-}
-
-} // namespace MaximInterface
-
-#endif
--- a/Utilities/span.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,366 +0,0 @@
-/*******************************************************************************
-* Copyright (C) 2018 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_span
-#define MaximInterface_span
-
-#include <stddef.h>
-#include <algorithm>
-#include <iterator>
-#include <vector>
-#include "array.hpp"
-#include "type_traits.hpp"
-
-namespace MaximInterface {
-
-static const ptrdiff_t dynamic_extent = -1;
-
-struct with_container_t {
-  explicit with_container_t(int) {}
-};
-
-static const with_container_t with_container(0);
-
-namespace detail {
-
-template <template <typename, ptrdiff_t = MaximInterface::dynamic_extent>
-          class span,
-          typename T, ptrdiff_t Extent>
-class span_base {
-public:
-  typedef T element_type;
-  typedef typename remove_cv<element_type>::type value_type;
-  typedef ptrdiff_t index_type;
-  typedef ptrdiff_t difference_type;
-  typedef element_type * pointer;
-  typedef element_type & reference;
-  typedef element_type * iterator;
-  typedef const element_type * const_iterator;
-  typedef std::reverse_iterator<iterator> reverse_iterator;
-  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-
-  static const index_type extent = Extent;
-
-protected:
-  span_base(pointer data) : data_(data) {}
-  ~span_base() {}
-
-public:
-  /// @name Iterators
-  /// @{
-  
-  iterator begin() const {
-    return const_cast<iterator>(static_cast<const span_base &>(*this).cbegin());
-  }
-  
-  const_iterator cbegin() const { return data(); }
-  
-  iterator end() const {
-    return const_cast<iterator>(static_cast<const span_base &>(*this).cend());
-  }
-  
-  const_iterator cend() const { return cbegin() + size(); }
-  
-  reverse_iterator rbegin() const { return reverse_iterator(end()); }
-  
-  const_reverse_iterator crbegin() const {
-    return const_reverse_iterator(cend());
-  }
-  
-  reverse_iterator rend() const { return reverse_iterator(begin()); }
-  
-  const_reverse_iterator crend() const {
-    return const_reverse_iterator(cbegin());
-  }
-  
-  /// @}
-
-  /// @name Element access
-  /// @{
-  
-  reference operator[](index_type idx) const { return data()[idx]; }
-  
-  reference operator()(index_type idx) const { return operator[](idx); }
-  
-  pointer data() const { return data_; }
-  
-  /// @}
-
-  /// @name Subviews
-  /// @{
-  
-  template <index_type Count> span<element_type, Count> first() const {
-    return subspan<0, Count>();
-  }
-  
-  span<element_type> first(index_type Count) const { return subspan(0, Count); }
-  
-  span<element_type> last(index_type Count) const {
-    return subspan(size() - Count, Count);
-  }
-  
-  template <index_type Offset, index_type Count>
-  span<element_type, Count> subspan() const {
-    return span<element_type, Count>(data() + Offset, Count);
-  }
-  
-  span<element_type> subspan(index_type Offset,
-                             index_type Count = dynamic_extent) const {
-    return span<element_type>(
-        data() + Offset, Count == dynamic_extent ? size() - Offset : Count);
-  }
-  
-  /// @}
-
-private:
-  index_type size() const {
-    return static_cast<const span<T, Extent> &>(*this).size();
-  }
-
-  pointer data_;
-};
-
-} // namespace detail
-
-/// Generic memory span class similar to gsl::span or the proposed std::span.
-template <typename T, ptrdiff_t Extent = dynamic_extent>
-class span : public detail::span_base<MaximInterface::span, T, Extent> {
-  typedef detail::span_base<MaximInterface::span, T, Extent> span_base;
-
-public:
-  using span_base::extent;
-  using typename span_base::element_type;
-  using typename span_base::index_type;
-  using typename span_base::pointer;
-  using typename span_base::value_type;
-
-  span(pointer data, index_type) : span_base(data) {}
-  
-  span(pointer begin, pointer) : span_base(begin) {}
-  
-  span(element_type (&arr)[extent]) : span_base(arr) {}
-  
-  span(array<value_type, extent> & arr) : span_base(arr.data()) {}
-  
-  span(const array<value_type, extent> & arr) : span_base(arr.data()) {}
-  
-  template <typename U> span(const span<U, extent> & s) : span_base(s.data()) {}
-  
-  template <typename Allocator>
-  explicit span(std::vector<value_type, Allocator> & vec)
-      : span_base(&vec.front()) {}
-      
-  template <typename Allocator>
-  explicit span(const std::vector<value_type, Allocator> & vec)
-      : span_base(&vec.front()) {}
-      
-  template <typename Container>
-  span(with_container_t, Container & cont) : span_base(cont.data()) {}
-  
-  template <typename Container>
-  span(with_container_t, const Container & cont) : span_base(cont.data()) {}
-
-  /// @name Observers
-  /// @{
-  
-  static index_type size() { return extent; }
-  
-  static index_type size_bytes() { return size() * sizeof(element_type); }
-  
-  static bool empty() { return size() == 0; }
-  
-  /// @}
-
-  /// @name Subviews
-  /// @{
-  
-  template <index_type Count> span<element_type, Count> last() const {
-    return this->template subspan<extent - Count, Count>();
-  }
-  
-  /// @}
-};
-
-template <typename T>
-class span<T, dynamic_extent>
-    : public detail::span_base<MaximInterface::span, T, dynamic_extent> {
-  typedef detail::span_base<MaximInterface::span, T, dynamic_extent> span_base;
-
-public:
-  using typename span_base::element_type;
-  using typename span_base::index_type;
-  using typename span_base::pointer;
-  using typename span_base::value_type;
-
-  span() : span_base(NULL), size_(0) {}
-  
-  span(pointer data, index_type size) : span_base(data), size_(size) {}
-  
-  span(pointer begin, pointer end) : span_base(begin), size_(end - begin) {}
-  
-  template <size_t N> span(element_type (&arr)[N]) : span_base(arr), size_(N) {}
-  
-  template <size_t N>
-  span(array<value_type, N> & arr) : span_base(arr.data()), size_(N) {}
-  
-  template <size_t N>
-  span(const array<value_type, N> & arr) : span_base(arr.data()), size_(N) {}
-  
-  template <typename U, ptrdiff_t N>
-  span(const span<U, N> & s) : span_base(s.data()), size_(s.size()) {}
-  
-  template <typename Allocator>
-  span(std::vector<value_type, Allocator> & vec)
-      : span_base(vec.empty() ? NULL : &vec.front()), size_(vec.size()) {}
-      
-  template <typename Allocator>
-  span(const std::vector<value_type, Allocator> & vec)
-      : span_base(vec.empty() ? NULL : &vec.front()), size_(vec.size()) {}
-      
-  template <typename Container>
-  span(with_container_t, Container & cont)
-      : span_base(cont.data()), size_(cont.size()) {}
-      
-  template <typename Container>
-  span(with_container_t, const Container & cont)
-      : span_base(cont.data()), size_(cont.size()) {}
-
-  /// @name Observers
-  /// @{
-  
-  index_type size() const { return size_; }
-  
-  index_type size_bytes() const { return size() * sizeof(element_type); }
-  
-  bool empty() const { return size() == 0; }
-  
-  /// @}
-
-  /// @name Subviews
-  /// @{
-  
-  template <index_type Count> span<element_type, Count> last() const {
-    return span<element_type, Count>(this->data() + (size() - Count), Count);
-  }
-  
-  /// @}
-
-private:
-  index_type size_;
-};
-
-template <typename T, ptrdiff_t Extent, typename U>
-bool operator==(span<T, Extent> lhs, span<U, Extent> rhs) {
-  return lhs.size() == rhs.size() &&
-         std::equal(lhs.begin(), lhs.end(), rhs.begin());
-}
-
-template <typename T, ptrdiff_t Extent, typename U>
-bool operator!=(span<T, Extent> lhs, span<U, Extent> rhs) {
-  return !operator==(lhs, rhs);
-}
-
-template <typename T, ptrdiff_t Extent, typename U>
-bool operator<(span<T, Extent> lhs, span<U, Extent> rhs) {
-  return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(),
-                                      rhs.end());
-}
-
-template <typename T, ptrdiff_t Extent, typename U>
-bool operator>(span<T, Extent> lhs, span<U, Extent> rhs) {
-  return operator<(rhs, lhs);
-}
-
-template <typename T, ptrdiff_t Extent, typename U>
-bool operator<=(span<T, Extent> lhs, span<U, Extent> rhs) {
-  return !operator>(lhs, rhs);
-}
-
-template <typename T, ptrdiff_t Extent, typename U>
-bool operator>=(span<T, Extent> lhs, span<U, Extent> rhs) {
-  return !operator<(lhs, rhs);
-}
-
-template <typename T>
-span<T> make_span(T * data, typename span<T>::index_type size) {
-  return span<T>(data, size);
-}
-
-template <typename T> span<T> make_span(T * begin, T * end) {
-  return span<T>(begin, end);
-}
-
-template <typename T, size_t N> span<T, N> make_span(T (&arr)[N]) {
-  return span<T, N>(arr);
-}
-
-template <typename T, size_t N> span<T, N> make_span(array<T, N> & arr) {
-  return arr;
-}
-
-template <typename T, size_t N>
-span<const T, N> make_span(const array<T, N> & arr) {
-  return arr;
-}
-
-template <typename T, typename Allocator>
-span<T> make_span(std::vector<T, Allocator> & vec) {
-  return vec;
-}
-
-template <typename T, typename Allocator>
-span<const T> make_span(const std::vector<T, Allocator> & vec) {
-  return vec;
-}
-
-template <typename Container>
-span<typename Container::value_type> make_span(with_container_t,
-                                               Container & cont) {
-  return span<typename Container::value_type>(with_container, cont);
-}
-
-template <typename Container>
-span<const typename Container::value_type> make_span(with_container_t,
-                                                     const Container & cont) {
-  return span<const typename Container::value_type>(with_container, cont);
-}
-
-/// Deep copy between static spans of the same size.
-template <typename T, ptrdiff_t Extent, typename U>
-typename enable_if<Extent != dynamic_extent>::type copy(span<T, Extent> src,
-                                                        span<U, Extent> dst) {
-  std::copy(src.begin(), src.end(), dst.begin());
-}
-
-} // namespace MaximInterface
-
-#endif
--- a/Utilities/system_error.cpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*******************************************************************************
-* 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 {
-
-using std::string;
-
-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 string message(int condition) const {
-      return defaultErrorMessage(condition);
-    }
-  } instance;
-  return instance;
-}
-
-static string formatWhat(const error_code & ec) {
-  return string(ec.category().name()) + ' ' + ec.message();
-}
-
-template <typename T>
-static string formatWhat(const error_code & ec, const T & what_arg) {
-  return string(what_arg) + ": " + formatWhat(ec);
-}
-
-system_error::system_error(const error_code & ec)
-    : runtime_error(formatWhat(ec)), code_(ec) {}
-
-system_error::system_error(const error_code & ec, const string & what_arg)
-    : runtime_error(formatWhat(ec, what_arg)), code_(ec) {}
-    
-system_error::system_error(const error_code & ec, const char * what_arg)
-    : runtime_error(formatWhat(ec, what_arg)), code_(ec) {}
-
-system_error::system_error(int ev, const error_category & ecat)
-    : runtime_error(formatWhat(error_code(ev, ecat))), code_(ev, ecat) {}
-
-system_error::system_error(int ev, const error_category & ecat,
-                           const string & what_arg)
-    : runtime_error(formatWhat(error_code(ev, ecat), what_arg)),
-      code_(ev, ecat) {}
-      
-system_error::system_error(int ev, const error_category & ecat,
-                           const char * what_arg)
-    : runtime_error(formatWhat(error_code(ev, ecat), what_arg)),
-      code_(ev, ecat) {}
-
-} // namespace MaximInterface
--- a/Utilities/system_error.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,227 +0,0 @@
-/*******************************************************************************
-* 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
-/// @brief
-/// Error handling constructs similar to std::error_code, std::error_condition,
-/// and std::error_category.
-
-#ifndef MaximInterface_system_error
-#define MaximInterface_system_error
-
-#include <stdexcept>
-#include <string>
-#include "Export.h"
-#include "SafeBool.hpp"
-#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 SafeBool() const { return makeSafeBool(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 SafeBool() const { return makeSafeBool(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);
-}
-
-class system_error : public std::runtime_error {
-public:
-  MaximInterface_EXPORT system_error(const error_code & ec);
-  
-  MaximInterface_EXPORT system_error(const error_code & ec,
-                                     const std::string & what_arg);
-                                     
-  MaximInterface_EXPORT system_error(const error_code & ec,
-                                     const char * what_arg);
-                                     
-  MaximInterface_EXPORT system_error(int ev, const error_category & ecat);
-  
-  MaximInterface_EXPORT system_error(int ev, const error_category & ecat,
-                                     const std::string & what_arg);
-                                     
-  MaximInterface_EXPORT system_error(int ev, const error_category & ecat,
-                                     const char * what_arg);
-
-  const error_code & code() const { return code_; }
-
-private:
-  error_code code_;
-};
-
-} // namespace MaximInterface
-
-#endif
--- a/Utilities/type_traits.hpp	Mon Mar 04 08:10:00 2019 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*******************************************************************************
-* 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 value_type() const { return value; }
-  value_type operator()() const { return value; }
-};
-
-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)> {};
-                        
-template <typename T> struct remove_const { typedef T type; };
-template <typename T> struct remove_const<const T> { typedef T type; };
-
-template <typename T> struct remove_volatile { typedef T type; };
-template <typename T> struct remove_volatile<volatile T> { typedef T type; };
-
-template <typename T> struct remove_cv {
-  typedef typename remove_volatile<typename remove_const<T>::type>::type type;
-};
-
-} // namespace MaximInterface
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_lib.json	Mon Jul 22 11:44:07 2019 -0500
@@ -0,0 +1,4 @@
+{
+  "name": "MaximInterface",
+  "macros": ["__STDC_LIMIT_MACROS"]
+}
\ No newline at end of file