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 Sep 16 11:13:37 2019 -0500
Parent:
7:9cd16581b578
Child:
9:fa054cc51fdb
Commit message:
Updated to version 2.0.

Changed in this revision

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 diff for this revision Revisions of this file
MaximInterfaceCore/HexConversions.hpp Show diff for this revision Revisions of this file
MaximInterfaceCore/HexString.cpp Show annotated file Show diff for this revision Revisions of this file
MaximInterfaceCore/HexString.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/Result.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 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
mbed_lib.json Show diff for this revision Revisions of this file
--- a/MaximInterfaceCore/Algorithm.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/Algorithm.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_Algorithm
-#define MaximInterfaceCore_Algorithm
+#ifndef MaximInterfaceCore_Algorithm_hpp
+#define MaximInterfaceCore_Algorithm_hpp
 
 #include <algorithm>
 #include "span.hpp"
--- a/MaximInterfaceCore/ChangeSizeType.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/ChangeSizeType.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,14 +30,14 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_ChangeSizeType
-#define MaximInterfaceCore_ChangeSizeType
+#ifndef MaximInterfaceCore_ChangeSizeType_hpp
+#define MaximInterfaceCore_ChangeSizeType_hpp
 
 #include <stdint.h>
 #include <algorithm>
 #include <limits>
+#include "Result.hpp"
 #include "span.hpp"
-#include "system_error.hpp"
 
 namespace MaximInterfaceCore {
 
@@ -50,10 +50,9 @@
 /// @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) {
+Result<void> 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())) {
@@ -62,15 +61,17 @@
       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()));
+      MaximInterfaceCore_TRY(
+          func(chunk.data(), static_cast<NewSize>(chunk.size())));
       dataIdx += chunk.size();
-    } while (dataIdx < data.size() && !result);
+    } while (dataIdx < data.size());
   } else {
-    result = func(data.data(), static_cast<NewSize>(data.size()));
+    MaximInterfaceCore_TRY(
+        func(data.data(), static_cast<NewSize>(data.size())));
   }
-  return result;
+  return none;
 }
 
 } // namespace MaximInterfaceCore
 
-#endif
\ No newline at end of file
+#endif
--- a/MaximInterfaceCore/Config.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/Config.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
--- a/MaximInterfaceCore/Ecc256.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/Ecc256.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -40,16 +40,29 @@
   copy(src.y, dst.y);
 }
 
+bool equal(Point::const_span lhs, Point::const_span rhs) {
+  return equal(lhs.x, rhs.x) && equal(lhs.y, rhs.y);
+}
+
 void copy(KeyPair::const_span src, KeyPair::span dst) {
   copy(src.privateKey, dst.privateKey);
   copy(src.publicKey, dst.publicKey);
 }
 
+bool equal(KeyPair::const_span lhs, KeyPair::const_span rhs) {
+  return equal(lhs.privateKey, rhs.privateKey) &&
+         equal(lhs.publicKey, rhs.publicKey);
+}
+
 void copy(Signature::const_span src, Signature::span dst) {
   copy(src.r, dst.r);
   copy(src.s, dst.s);
 }
 
+bool equal(Signature::const_span lhs, Signature::const_span rhs) {
+  return equal(lhs.r, rhs.r) && equal(lhs.s, rhs.s);
+}
+
 PublicKey::span CertificateData::publicKey() {
   const PublicKey::span span = {
       make_span(result_).subspan<publicKeyIdx, Scalar::size>(),
--- a/MaximInterfaceCore/Ecc256.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/Ecc256.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_Ecc256
-#define MaximInterfaceCore_Ecc256
+#ifndef MaximInterfaceCore_Ecc256_hpp
+#define MaximInterfaceCore_Ecc256_hpp
 
 #include <stdint.h>
 #include "Algorithm.hpp"
@@ -80,6 +80,9 @@
 
 MaximInterfaceCore_EXPORT void copy(Point::const_span src, Point::span dst);
 
+MaximInterfaceCore_EXPORT bool equal(Point::const_span lhs,
+                                     Point::const_span rhs);
+
 typedef Scalar PrivateKey;
 typedef Point PublicKey;
 
@@ -117,6 +120,9 @@
 
 MaximInterfaceCore_EXPORT void copy(KeyPair::const_span src, KeyPair::span dst);
 
+MaximInterfaceCore_EXPORT bool equal(KeyPair::const_span lhs,
+                                     KeyPair::const_span rhs);
+
 struct Signature : Unconstructible {
   struct const_span {
     Scalar::const_span r;
@@ -152,6 +158,9 @@
 MaximInterfaceCore_EXPORT void copy(Signature::const_span src,
                                     Signature::span dst);
 
+MaximInterfaceCore_EXPORT bool equal(Signature::const_span lhs,
+                                     Signature::const_span rhs);
+
 /// Data used to create a device key certificate for ECC-256 authenticators.
 class CertificateData {
 public:
@@ -229,11 +238,9 @@
   /// @}
 
 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;
+  static const size_t publicKeyIdx = 0;
+  static const size_t romIdIdx = publicKeyIdx + 2 * Scalar::size;
+  static const size_t manIdIdx = romIdIdx + RomId::size;
 
   Result::array result_;
 };
--- a/MaximInterfaceCore/Error.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/Error.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
--- a/MaximInterfaceCore/Error.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/Error.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_Error
-#define MaximInterfaceCore_Error
+#ifndef MaximInterfaceCore_Error_hpp
+#define MaximInterfaceCore_Error_hpp
 
 #include "Config.hpp"
 
--- a/MaximInterfaceCore/FlagSet.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/FlagSet.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_FlagSet
-#define MaximInterfaceCore_FlagSet
+#ifndef MaximInterfaceCore_FlagSet_hpp
+#define MaximInterfaceCore_FlagSet_hpp
 
 #include <stddef.h>
 #include <bitset>
@@ -58,7 +58,7 @@
 
     operator bool() const { return flagSet->test(flag); }
 
-    bool operator~() const { return reference(*this).flip(); }
+    bool operator~() const { return !*this; }
 
     reference & flip() {
       *this = !*this;
@@ -93,7 +93,10 @@
 
   reference operator[](Flag flag) { return reference(*this, flag); }
 
-  bool test(Flag flag) const { return (bits.to_ulong() & flag) == flag; }
+  bool test(Flag flag) const {
+    const unsigned long rawFlag = static_cast<unsigned long>(flag);
+    return (bits.to_ulong() & rawFlag) == rawFlag;
+  }
 
   bool any() const { return bits.any(); }
 
@@ -136,10 +139,11 @@
   }
 
   FlagSet & set(Flag flag, bool value = true) {
+    const unsigned long rawFlag = static_cast<unsigned long>(flag);
     if (value) {
-      bits |= flag;
+      bits |= rawFlag;
     } else {
-      bits &= ~std::bitset<flagBits>(flag);
+      bits &= ~rawFlag;
     }
     return *this;
   }
@@ -157,7 +161,7 @@
   }
 
   FlagSet & flip(Flag flag) {
-    bits ^= flag;
+    bits ^= static_cast<unsigned long>(flag);
     return *this;
   }
 
--- a/MaximInterfaceCore/Function.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/Function.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,10 +30,11 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_Function
-#define MaximInterfaceCore_Function
+#ifndef MaximInterfaceCore_Function_hpp
+#define MaximInterfaceCore_Function_hpp
 
 #include <stddef.h>
+#include "None.hpp"
 #include "SafeBool.hpp"
 #include "type_traits.hpp"
 
@@ -112,6 +113,8 @@
 public:
   TypeWrapper() : currentTarget(NULL) {}
 
+  TypeWrapper(None) : currentTarget(NULL) {}
+
   TypeWrapper(const TypeWrapper & other) {
     if (other.currentTarget == other.internalTarget) {
       other.currentTarget->clone(internalTarget);
@@ -142,6 +145,11 @@
     }
   }
 
+  const TypeWrapper & operator=(None) {
+    TypeWrapper().swap(*this);
+    return *this;
+  }
+
   const TypeWrapper & operator=(const TypeWrapper & rhs) {
     TypeWrapper(rhs).swap(*this);
     return *this;
@@ -152,8 +160,6 @@
     return *this;
   }
 
-  void clear() { TypeWrapper().swap(*this); }
-
   void swap(TypeWrapper & other) {
     if (this == &other) {
       return;
@@ -201,6 +207,8 @@
 public:
   TypeWrapper() : currentTarget(NULL) {}
 
+  TypeWrapper(None) : currentTarget(NULL) {}
+
   TypeWrapper(const TypeWrapper & other) {
     if (other.currentTarget) {
       currentTarget = other.currentTarget->clone();
@@ -215,6 +223,11 @@
 
   ~TypeWrapper() { delete currentTarget; }
 
+  const TypeWrapper & operator=(None) {
+    TypeWrapper().swap(*this);
+    return *this;
+  }
+
   const TypeWrapper & operator=(const TypeWrapper & rhs) {
     TypeWrapper(rhs).swap(*this);
     return *this;
@@ -225,8 +238,6 @@
     return *this;
   }
 
-  void clear() { TypeWrapper().swap(*this); }
-
   void swap(TypeWrapper & other) {
     using std::swap;
     swap(currentTarget, other.currentTarget);
@@ -240,15 +251,19 @@
 
 } // namespace detail
 
-// Function wrapper similar to std::function for 0-3 argument functions.
+/// %Function wrapper similar to std::function for 0-3 argument functions.
 template <typename> class Function;
 
-// Function implementation for zero argument functions.
+/// Function implementation for zero argument functions.
 template <typename ResultType> class Function<ResultType()> {
 public:
   typedef ResultType result_type;
 
-  Function(ResultType (*func)() = NULL) : callableWrapper() {
+  Function() : callableWrapper() {}
+
+  Function(None) : callableWrapper() {}
+
+  Function(ResultType (*func)()) : callableWrapper() {
     if (func) {
       callableWrapper = func;
     }
@@ -256,11 +271,16 @@
 
   template <typename F> Function(F func) : callableWrapper(func) {}
 
+  const Function & operator=(None) {
+    callableWrapper = none;
+    return *this;
+  }
+
   const Function & operator=(ResultType (*func)()) {
     if (func) {
       callableWrapper = func;
     } else {
-      callableWrapper.clear();
+      callableWrapper = none;
     }
     return *this;
   }
@@ -314,14 +334,18 @@
   lhs.swap(rhs);
 }
 
-// Function implementation for one argument functions.
+/// 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() {
+  Function() : callableWrapper() {}
+
+  Function(None) : callableWrapper() {}
+
+  Function(ResultType (*func)(ArgumentType)) : callableWrapper() {
     if (func) {
       callableWrapper = func;
     }
@@ -329,11 +353,16 @@
 
   template <typename F> Function(F func) : callableWrapper(func) {}
 
+  const Function & operator=(None) {
+    callableWrapper = none;
+    return *this;
+  }
+
   const Function & operator=(ResultType (*func)(ArgumentType)) {
     if (func) {
       callableWrapper = func;
     } else {
-      callableWrapper.clear();
+      callableWrapper = none;
     }
     return *this;
   }
@@ -388,7 +417,7 @@
   lhs.swap(rhs);
 }
 
-// Function implementation for two argument functions.
+/// Function implementation for two argument functions.
 template <typename FirstArgumentType, typename SecondArgumentType,
           typename ResultType>
 class Function<ResultType(FirstArgumentType, SecondArgumentType)> {
@@ -397,7 +426,11 @@
   typedef SecondArgumentType second_argument_type;
   typedef ResultType result_type;
 
-  Function(ResultType (*func)(FirstArgumentType, SecondArgumentType) = NULL)
+  Function() : callableWrapper() {}
+
+  Function(None) : callableWrapper() {}
+
+  Function(ResultType (*func)(FirstArgumentType, SecondArgumentType))
       : callableWrapper() {
     if (func) {
       callableWrapper = func;
@@ -406,12 +439,17 @@
 
   template <typename F> Function(F func) : callableWrapper(func) {}
 
+  const Function & operator=(None) {
+    callableWrapper = none;
+    return *this;
+  }
+
   const Function & operator=(ResultType (*func)(FirstArgumentType,
                                                 SecondArgumentType)) {
     if (func) {
       callableWrapper = func;
     } else {
-      callableWrapper.clear();
+      callableWrapper = none;
     }
     return *this;
   }
@@ -472,7 +510,7 @@
   lhs.swap(rhs);
 }
 
-// Function implementation for three argument functions.
+/// Function implementation for three argument functions.
 template <typename FirstArgumentType, typename SecondArgumentType,
           typename ThirdArgumentType, typename ResultType>
 class Function<ResultType(FirstArgumentType, SecondArgumentType,
@@ -480,8 +518,12 @@
 public:
   typedef ResultType result_type;
 
+  Function() : callableWrapper() {}
+
+  Function(None) : callableWrapper() {}
+
   Function(ResultType (*func)(FirstArgumentType, SecondArgumentType,
-                              ThirdArgumentType) = NULL)
+                              ThirdArgumentType))
       : callableWrapper() {
     if (func) {
       callableWrapper = func;
@@ -490,13 +532,18 @@
 
   template <typename F> Function(F func) : callableWrapper(func) {}
 
+  const Function & operator=(None) {
+    callableWrapper = none;
+    return *this;
+  }
+
   const Function & operator=(ResultType (*func)(FirstArgumentType,
                                                 SecondArgumentType,
                                                 ThirdArgumentType)) {
     if (func) {
       callableWrapper = func;
     } else {
-      callableWrapper.clear();
+      callableWrapper = none;
     }
     return *this;
   }
--- a/MaximInterfaceCore/HexConversions.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ /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 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
--- a/MaximInterfaceCore/HexConversions.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ /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 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/HexString.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -0,0 +1,86 @@
+/*******************************************************************************
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade 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 "HexString.hpp"
+
+namespace MaximInterfaceCore {
+
+using std::string;
+using std::vector;
+
+static const int charsPerByte = 2;
+
+string toHexString(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> >
+fromHexString(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/HexString.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -0,0 +1,55 @@
+/*******************************************************************************
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade 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_HexString_hpp
+#define MaximInterfaceCore_HexString_hpp
+
+#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
+toHexString(span<const uint_least8_t> byteArray);
+
+/// Convert a hex string to a byte array.
+MaximInterfaceCore_EXPORT Optional<std::vector<uint_least8_t> >
+fromHexString(const std::string & hexString);
+
+} // namespace MaximInterfaceCore
+
+#endif
--- a/MaximInterfaceCore/I2CMaster.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/I2CMaster.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -35,48 +35,46 @@
 
 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]);
+Result<void> I2CMaster::writeBlock(span<const uint_least8_t> data) {
+  for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) {
+    MaximInterfaceCore_TRY(writeByte(data[i]));
   }
-  return result;
+  return none;
 }
 
-error_code I2CMaster::doWritePacket(uint_least8_t address,
+Result<void> I2CMaster::writePacket(uint_least8_t address,
                                     span<const uint_least8_t> data,
-                                    bool sendStop) {
-  error_code result = start(address & 0xFE);
-  if (!result) {
+                                    DoStop doStop) {
+  Result<void> result = start(address & 0xFE);
+  if (result) {
     result = writeBlock(data);
   }
-  if (sendStop) {
-    error_code stopResult = stop();
-    if (!result) {
+  if (doStop == Stop || (doStop == StopOnError && !result)) {
+    const Result<void> 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]);
+Result<void> I2CMaster::readBlock(span<uint_least8_t> data, DoAck doAck) {
+  for (span<uint_least8_t>::index_type i = 0; i < data.size(); ++i) {
+    MaximInterfaceCore_TRY_VALUE(
+        data[i], readByte(i == (data.size() - 1) ? doAck : Ack));
   }
-  return result;
+  return none;
 }
 
-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);
+Result<void> I2CMaster::readPacket(uint_least8_t address,
+                                   span<uint_least8_t> data, DoStop doStop) {
+  Result<void> result = start(address | 0x01);
+  if (result) {
+    result = readBlock(data, Nack);
   }
-  if (sendStop) {
-    error_code stopResult = stop();
-    if (!result) {
+  if (doStop == Stop || (doStop == StopOnError && !result)) {
+    const Result<void> stopResult = stop();
+    if (result) {
       result = stopResult;
     }
   }
@@ -92,10 +90,8 @@
       switch (condition) {
       case NackError:
         return "Nack Error";
-
-      default:
-        return defaultErrorMessage(condition);
       }
+      return defaultErrorMessage(condition);
     }
   } instance;
   return instance;
--- a/MaximInterfaceCore/I2CMaster.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/I2CMaster.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,11 +30,12 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_I2CMaster
-#define MaximInterfaceCore_I2CMaster
+#ifndef MaximInterfaceCore_I2CMaster_hpp
+#define MaximInterfaceCore_I2CMaster_hpp
 
 #include <stdint.h>
 #include "Config.hpp"
+#include "Result.hpp"
 #include "span.hpp"
 #include "system_error.hpp"
 
@@ -47,69 +48,58 @@
     NackError = 1 ///< Transaction stopped due to a NACK from the slave device.
   };
 
-  enum AckStatus { Nack, Ack };
+  enum DoAck { Ack, Nack };
+
+  enum DoStop { Stop, StopOnError, NoStop };
 
   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;
+  virtual Result<void> start(uint_least8_t address) = 0;
 
   /// Send stop condition on the bus.
-  virtual error_code stop() = 0;
+  virtual Result<void> stop() = 0;
 
   /// Write data byte to the bus.
-  virtual error_code writeByte(uint_least8_t data) = 0;
+  virtual Result<void> writeByte(uint_least8_t data) = 0;
 
   /// Write data block to the bus.
-  MaximInterfaceCore_EXPORT virtual error_code
+  MaximInterfaceCore_EXPORT virtual Result<void>
   writeBlock(span<const uint_least8_t> data);
 
-  /// @brief
-  /// Perform a complete write transaction on the bus with optional stop
-  /// condition.
+  /// @brief Perform a complete write transaction on the bus.
   /// @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);
-  }
+  /// @param doStop
+  /// Determines whether to do a stop condition or set up a repeated start.
+  MaximInterfaceCore_EXPORT virtual Result<void>
+  writePacket(uint_least8_t address, span<const uint_least8_t> data,
+              DoStop doStop);
 
   /// @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;
+  /// @param doAck Determines whether an ACK or NACK is done after reading.
+  /// @returns data Data read from the bus if successful.
+  virtual Result<uint_least8_t> readByte(DoAck doAck) = 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);
+  /// @param doAck Determines whether an ACK or NACK is done after reading.
+  MaximInterfaceCore_EXPORT virtual Result<void>
+  readBlock(span<uint_least8_t> data, DoAck doAck);
 
-  /// @brief
-  /// Perform a complete read transaction on the bus with optional stop
-  /// condition.
+  /// @brief Perform a complete read transaction on the bus.
   /// @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);
-  }
+  /// @param doStop
+  /// Determines whether to do a stop condition or set up a repeated start.
+  MaximInterfaceCore_EXPORT virtual Result<void>
+  readPacket(uint_least8_t address, span<uint_least8_t> data, DoStop doStop);
 
   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);
-};
+template <> struct is_error_code_enum<I2CMaster::ErrorValue> : true_type {};
 
 inline error_code make_error_code(I2CMaster::ErrorValue e) {
   return error_code(e, I2CMaster::errorCategory());
--- a/MaximInterfaceCore/I2CMasterDecorator.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/I2CMasterDecorator.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -34,40 +34,39 @@
 
 namespace MaximInterfaceCore {
 
-error_code I2CMasterDecorator::start(uint_least8_t address) {
+Result<void> I2CMasterDecorator::start(uint_least8_t address) {
   return master->start(address);
 }
 
-error_code I2CMasterDecorator::stop() { return master->stop(); }
+Result<void> I2CMasterDecorator::stop() { return master->stop(); }
 
-error_code I2CMasterDecorator::writeByte(uint_least8_t data) {
+Result<void> I2CMasterDecorator::writeByte(uint_least8_t data) {
   return master->writeByte(data);
 }
 
-error_code I2CMasterDecorator::writeBlock(span<const uint_least8_t> data) {
+Result<void> I2CMasterDecorator::writeBlock(span<const uint_least8_t> data) {
   return master->writeBlock(data);
 }
 
-error_code I2CMasterDecorator::doWritePacket(uint_least8_t address,
+Result<void> I2CMasterDecorator::writePacket(uint_least8_t address,
                                              span<const uint_least8_t> data,
-                                             bool sendStop) {
-  return master->writePacket(address, data, sendStop);
+                                             DoStop doStop) {
+  return master->writePacket(address, data, doStop);
+}
+
+Result<uint_least8_t> I2CMasterDecorator::readByte(DoAck doAck) {
+  return master->readByte(doAck);
 }
 
-error_code I2CMasterDecorator::readByte(AckStatus status,
-                                        uint_least8_t & data) {
-  return master->readByte(status, data);
+Result<void> I2CMasterDecorator::readBlock(span<uint_least8_t> data,
+                                           DoAck doAck) {
+  return master->readBlock(data, doAck);
 }
 
-error_code I2CMasterDecorator::readBlock(AckStatus status,
-                                         span<uint_least8_t> data) {
-  return master->readBlock(status, data);
-}
-
-error_code I2CMasterDecorator::doReadPacket(uint_least8_t address,
+Result<void> I2CMasterDecorator::readPacket(uint_least8_t address,
                                             span<uint_least8_t> data,
-                                            bool sendStop) {
-  return master->readPacket(address, data, sendStop);
+                                            DoStop doStop) {
+  return master->readPacket(address, data, doStop);
 }
 
 } // namespace MaximInterfaceCore
--- a/MaximInterfaceCore/I2CMasterDecorator.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/I2CMasterDecorator.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_I2CMasterDecorator
-#define MaximInterfaceCore_I2CMasterDecorator
+#ifndef MaximInterfaceCore_I2CMasterDecorator_hpp
+#define MaximInterfaceCore_I2CMasterDecorator_hpp
 
 #include "Config.hpp"
 #include "I2CMaster.hpp"
@@ -45,28 +45,26 @@
 public:
   void setMaster(I2CMaster & master) { this->master = &master; }
 
-  MaximInterfaceCore_EXPORT virtual error_code start(uint_least8_t address);
+  MaximInterfaceCore_EXPORT virtual Result<void> start(uint_least8_t address);
 
-  MaximInterfaceCore_EXPORT virtual error_code stop();
+  MaximInterfaceCore_EXPORT virtual Result<void> stop();
 
-  MaximInterfaceCore_EXPORT virtual error_code writeByte(uint_least8_t data);
+  MaximInterfaceCore_EXPORT virtual Result<void> writeByte(uint_least8_t data);
 
-  MaximInterfaceCore_EXPORT virtual error_code
+  MaximInterfaceCore_EXPORT virtual Result<void>
   writeBlock(span<const uint_least8_t> data);
 
-  MaximInterfaceCore_EXPORT virtual error_code readByte(AckStatus status,
-                                                        uint_least8_t & data);
+  MaximInterfaceCore_EXPORT virtual Result<void>
+  writePacket(uint_least8_t address, span<const uint_least8_t> data,
+              DoStop doStop);
 
-  MaximInterfaceCore_EXPORT virtual error_code
-  readBlock(AckStatus status, span<uint_least8_t> data);
+  MaximInterfaceCore_EXPORT virtual Result<uint_least8_t> readByte(DoAck doAck);
 
-protected:
-  MaximInterfaceCore_EXPORT virtual error_code
-  doWritePacket(uint_least8_t address, span<const uint_least8_t> data,
-                bool sendStop);
+  MaximInterfaceCore_EXPORT virtual Result<void>
+  readBlock(span<uint_least8_t> data, DoAck doAck);
 
-  MaximInterfaceCore_EXPORT virtual error_code
-  doReadPacket(uint_least8_t address, span<uint_least8_t> data, bool sendStop);
+  MaximInterfaceCore_EXPORT virtual Result<void>
+  readPacket(uint_least8_t address, span<uint_least8_t> data, DoStop doStop);
 
 private:
   I2CMaster * master;
--- a/MaximInterfaceCore/LoggingI2CMaster.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/LoggingI2CMaster.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -31,7 +31,7 @@
 *******************************************************************************/
 
 #include <utility>
-#include "HexConversions.hpp"
+#include "HexString.hpp"
 #include "LoggingI2CMaster.hpp"
 
 using std::string;
@@ -47,7 +47,7 @@
     if (read) {
       dataBuilder.append(1, '[');
     }
-    dataBuilder.append(byteArrayToHexString(data.subspan(i, 1)));
+    dataBuilder.append(toHexString(data.subspan(i, 1)));
     if (read) {
       dataBuilder.append(1, ']');
     }
@@ -63,72 +63,73 @@
   messageBuilder.clear();
 }
 
-error_code LoggingI2CMaster::start(uint_least8_t address) {
+Result<void> 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() {
+Result<void> LoggingI2CMaster::stop() {
   messageBuilder.append(stopString);
   tryWriteMessage();
   return I2CMasterDecorator::stop();
 }
 
-error_code LoggingI2CMaster::writeByte(uint_least8_t data) {
+Result<void> 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) {
+Result<void> 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,
+Result<void> LoggingI2CMaster::writePacket(uint_least8_t address,
                                            span<const uint_least8_t> data,
-                                           bool sendStop) {
+                                           DoStop doStop) {
   messageBuilder.append(startString);
   messageBuilder.append(formatDataString(make_span(&address, 1), false));
-  error_code result =
-      I2CMasterDecorator::doWritePacket(address, data, sendStop);
-  if (!result) {
+  const Result<void> result =
+      I2CMasterDecorator::writePacket(address, data, doStop);
+  if (result) {
     messageBuilder.append(formatDataString(data, false));
   }
-  if (sendStop || result) {
+  if (doStop == Stop || (doStop == StopOnError && !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));
+Result<uint_least8_t> LoggingI2CMaster::readByte(DoAck doAck) {
+  const Result<uint_least8_t> data = I2CMasterDecorator::readByte(doAck);
+  if (data) {
+    messageBuilder.append(formatDataString(make_span(&data.value(), 1), true));
   }
-  return result;
+  return data;
 }
 
-error_code LoggingI2CMaster::readBlock(AckStatus status,
-                                       span<uint_least8_t> data) {
-  error_code result = I2CMasterDecorator::readBlock(status, data);
-  if (!result) {
+Result<void> LoggingI2CMaster::readBlock(span<uint_least8_t> data,
+                                         DoAck doAck) {
+  const Result<void> result = I2CMasterDecorator::readBlock(data, doAck);
+  if (result) {
     messageBuilder.append(formatDataString(data, true));
   }
   return result;
 }
 
-error_code LoggingI2CMaster::doReadPacket(uint_least8_t address,
+Result<void> LoggingI2CMaster::readPacket(uint_least8_t address,
                                           span<uint_least8_t> data,
-                                          bool sendStop) {
+                                          DoStop doStop) {
   messageBuilder.append(startString);
   messageBuilder.append(formatDataString(make_span(&address, 1), false));
-  error_code result = I2CMasterDecorator::doReadPacket(address, data, sendStop);
-  if (!result) {
+  const Result<void> result =
+      I2CMasterDecorator::readPacket(address, data, doStop);
+  if (result) {
     messageBuilder.append(formatDataString(data, true));
   }
-  if (sendStop || result) {
+  if (doStop == Stop || (doStop == StopOnError && !result)) {
     messageBuilder.append(stopString);
     tryWriteMessage();
   }
--- a/MaximInterfaceCore/LoggingI2CMaster.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/LoggingI2CMaster.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_LoggingI2CMaster
-#define MaximInterfaceCore_LoggingI2CMaster
+#ifndef MaximInterfaceCore_LoggingI2CMaster_hpp
+#define MaximInterfaceCore_LoggingI2CMaster_hpp
 
 #include <string>
 #include "Config.hpp"
@@ -50,27 +50,26 @@
     this->writeMessage = writeMessage;
   }
 
-  MaximInterfaceCore_EXPORT virtual error_code start(uint_least8_t address);
+  MaximInterfaceCore_EXPORT virtual Result<void> start(uint_least8_t address);
 
-  MaximInterfaceCore_EXPORT virtual error_code stop();
+  MaximInterfaceCore_EXPORT virtual Result<void> stop();
 
-  MaximInterfaceCore_EXPORT virtual error_code writeByte(uint_least8_t data);
+  MaximInterfaceCore_EXPORT virtual Result<void> writeByte(uint_least8_t data);
 
-  MaximInterfaceCore_EXPORT virtual error_code
+  MaximInterfaceCore_EXPORT virtual Result<void>
   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);
+  MaximInterfaceCore_EXPORT virtual Result<void>
+  writePacket(uint_least8_t address, span<const uint_least8_t> data,
+              DoStop doStop);
+
+  MaximInterfaceCore_EXPORT virtual Result<uint_least8_t> readByte(DoAck doAck);
 
-protected:
-  MaximInterfaceCore_EXPORT virtual error_code
-  doWritePacket(uint_least8_t address, span<const uint_least8_t> data,
-                bool sendStop);
+  MaximInterfaceCore_EXPORT virtual Result<void>
+  readBlock(span<uint_least8_t> data, DoAck doAck);
 
-  MaximInterfaceCore_EXPORT virtual error_code
-  doReadPacket(uint_least8_t address, span<uint_least8_t> data, bool sendStop);
+  MaximInterfaceCore_EXPORT virtual Result<void>
+  readPacket(uint_least8_t address, span<uint_least8_t> data, DoStop doStop);
 
 private:
   void tryWriteMessage();
--- a/MaximInterfaceCore/LoggingOneWireMaster.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/LoggingOneWireMaster.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 * ownership rights.
 *******************************************************************************/
 
-#include "HexConversions.hpp"
+#include "HexString.hpp"
 #include "LoggingOneWireMaster.hpp"
 
 using std::string;
@@ -45,7 +45,7 @@
     if (read) {
       dataBuilder.append(1, '[');
     }
-    dataBuilder.append(byteArrayToHexString(data.subspan(i, 1)));
+    dataBuilder.append(toHexString(data.subspan(i, 1)));
     if (read) {
       dataBuilder.append(1, ']');
     }
@@ -60,14 +60,14 @@
   }
 }
 
-error_code LoggingOneWireMaster::reset() {
-  error_code result = OneWireMasterDecorator::reset();
-  tryWriteMessage(!result ? "RP" : "RN");
+Result<void> LoggingOneWireMaster::reset() {
+  Result<void> result = OneWireMasterDecorator::reset();
+  tryWriteMessage(result ? "RP" : "RN");
   return result;
 }
 
-error_code LoggingOneWireMaster::writeByteSetLevel(uint_least8_t sendByte,
-                                                   Level afterLevel) {
+Result<void> LoggingOneWireMaster::writeByteSetLevel(uint_least8_t sendByte,
+                                                     Level afterLevel) {
   tryWriteMessage(formatDataString(make_span(&sendByte, 1), false));
   if (afterLevel == StrongLevel) {
     tryWriteMessage(strongLevelString);
@@ -75,35 +75,35 @@
   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));
+Result<uint_least8_t> LoggingOneWireMaster::readByteSetLevel(Level afterLevel) {
+  const Result<uint_least8_t> recvByte =
+      OneWireMasterDecorator::readByteSetLevel(afterLevel);
+  if (recvByte) {
+    tryWriteMessage(formatDataString(make_span(&recvByte.value(), 1), true));
     if (afterLevel == StrongLevel) {
       tryWriteMessage(strongLevelString);
     }
   }
-  return result;
+  return recvByte;
 }
 
-error_code LoggingOneWireMaster::writeBlock(span<const uint_least8_t> sendBuf) {
+Result<void>
+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) {
+Result<void> LoggingOneWireMaster::readBlock(span<uint_least8_t> recvBuf) {
+  Result<void> 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) {
+Result<void> LoggingOneWireMaster::setSpeed(Speed newSpeed) {
+  Result<void> result = OneWireMasterDecorator::setSpeed(newSpeed);
+  if (result) {
     string newSpeedString;
     switch (newSpeed) {
     case StandardSpeed:
@@ -121,9 +121,9 @@
   return result;
 }
 
-error_code LoggingOneWireMaster::setLevel(Level newLevel) {
-  error_code result = OneWireMasterDecorator::setLevel(newLevel);
-  if (!result) {
+Result<void> LoggingOneWireMaster::setLevel(Level newLevel) {
+  Result<void> result = OneWireMasterDecorator::setLevel(newLevel);
+  if (result) {
     string newLevelString;
     switch (newLevel) {
     case NormalLevel:
--- a/MaximInterfaceCore/LoggingOneWireMaster.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/LoggingOneWireMaster.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_LoggingOneWireMaster
-#define MaximInterfaceCore_LoggingOneWireMaster
+#ifndef MaximInterfaceCore_LoggingOneWireMaster_hpp
+#define MaximInterfaceCore_LoggingOneWireMaster_hpp
 
 #include <string>
 #include "Config.hpp"
@@ -51,23 +51,23 @@
     this->writeMessage = writeMessage;
   }
 
-  MaximInterfaceCore_EXPORT virtual error_code reset();
+  MaximInterfaceCore_EXPORT virtual Result<void> reset();
 
-  MaximInterfaceCore_EXPORT virtual error_code
+  MaximInterfaceCore_EXPORT virtual Result<void>
   writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
 
-  MaximInterfaceCore_EXPORT virtual error_code
-  readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+  MaximInterfaceCore_EXPORT virtual Result<uint_least8_t>
+  readByteSetLevel(Level afterLevel);
 
-  MaximInterfaceCore_EXPORT virtual error_code
+  MaximInterfaceCore_EXPORT virtual Result<void>
   writeBlock(span<const uint_least8_t> sendBuf);
 
-  MaximInterfaceCore_EXPORT virtual error_code
+  MaximInterfaceCore_EXPORT virtual Result<void>
   readBlock(span<uint_least8_t> recvBuf);
 
-  MaximInterfaceCore_EXPORT virtual error_code setSpeed(Speed newSpeed);
+  MaximInterfaceCore_EXPORT virtual Result<void> setSpeed(Speed newSpeed);
 
-  MaximInterfaceCore_EXPORT virtual error_code setLevel(Level newLevel);
+  MaximInterfaceCore_EXPORT virtual Result<void> setLevel(Level newLevel);
 
 private:
   void tryWriteMessage(const std::string & message);
--- a/MaximInterfaceCore/LoggingSleep.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/LoggingSleep.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
--- a/MaximInterfaceCore/LoggingSleep.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/LoggingSleep.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_LoggingSleep
-#define MaximInterfaceCore_LoggingSleep
+#ifndef MaximInterfaceCore_LoggingSleep_hpp
+#define MaximInterfaceCore_LoggingSleep_hpp
 
 #include "Config.hpp"
 #include "SleepDecorator.hpp"
--- a/MaximInterfaceCore/ManId.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/ManId.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_ManId
-#define MaximInterfaceCore_ManId
+#ifndef MaximInterfaceCore_ManId_hpp
+#define MaximInterfaceCore_ManId_hpp
 
 #include "array_span.hpp"
 
--- a/MaximInterfaceCore/None.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/None.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2019 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,17 +30,22 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_None
-#define MaximInterfaceCore_None
+#ifndef MaximInterfaceCore_None_hpp
+#define MaximInterfaceCore_None_hpp
 
 namespace MaximInterfaceCore {
 
+/// @brief Empty tag for use with Function, Optional, Result, and similar types.
+/// @details A predefined instance called "none" is provided.
+/// @see none
 struct None {
-  // Disable default constructor.
+  /// @private
+  /// @brief Disables default constructor.
   explicit None(int) {}
 };
 
-/// Empty tag for use with Optional and similar types.
+/// @copybrief None
+/// @details This is the predefined instance of the None type.
 static const None none(0);
 
 } // namespace MaximInterfaceCore
--- a/MaximInterfaceCore/OneWireMaster.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/OneWireMaster.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -33,71 +33,62 @@
 #include "Error.hpp"
 #include "OneWireMaster.hpp"
 
+#define TRY MaximInterfaceCore_TRY
+#define TRY_VALUE MaximInterfaceCore_TRY_VALUE
+
 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);
+Result<void> OneWireMaster::writeByteSetLevel(uint_least8_t sendByte,
+                                              Level afterLevel) {
+  for (int bitNum = 0; bitNum <= maxBitNum; ++bitNum) {
+    TRY(writeBitSetLevel(((sendByte >> bitNum) & 1) == 1,
+                         (bitNum == maxBitNum) ? afterLevel : NormalLevel));
   }
-  return result;
+  return none;
 }
 
-error_code OneWireMaster::readByteSetLevel(uint_least8_t & recvByte,
-                                           Level afterLevel) {
-  recvByte = 0;
-  error_code result;
+Result<uint_least8_t> OneWireMaster::readByteSetLevel(Level afterLevel) {
+  uint_least8_t recvByte = 0;
   for (int bitNum = 0; bitNum <= maxBitNum; ++bitNum) {
     bool recvBit;
-    result = readBitSetLevel(recvBit,
-                             (bitNum == maxBitNum) ? afterLevel : NormalLevel);
-    if (result) {
-      break;
-    }
+    TRY_VALUE(recvBit, readBitSetLevel((bitNum == maxBitNum) ? afterLevel
+                                                             : NormalLevel));
     if (recvBit) {
       recvByte |= (1 << bitNum);
     }
   }
-  return result;
+  return recvByte;
 }
 
-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]);
+Result<void> OneWireMaster::writeBlock(span<const uint_least8_t> sendBuf) {
+  for (span<const uint_least8_t>::index_type i = 0; i < sendBuf.size(); ++i) {
+    TRY(writeByte(sendBuf[i]));
   }
-  return result;
+  return none;
 }
 
-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]);
+Result<void> OneWireMaster::readBlock(span<uint_least8_t> recvBuf) {
+  for (span<uint_least8_t>::index_type i = 0; i < recvBuf.size(); ++i) {
+    TRY_VALUE(recvBuf[i], readByte());
   }
-  return result;
+  return none;
 }
 
-error_code OneWireMaster::triplet(TripletData & data) {
-  error_code result = readBit(data.readBit);
-  if (!result) {
-    result = readBit(data.readBitComplement);
+Result<OneWireMaster::TripletData> OneWireMaster::triplet(bool sendBit) {
+  TripletData data;
+  TRY_VALUE(data.readBit, readBit());
+  TRY_VALUE(data.readBitComplement, readBit());
+  if (data.readBit) {
+    data.writeBit = 1;
+  } else if (data.readBitComplement) {
+    data.writeBit = 0;
+  } else {
+    data.writeBit = sendBit;
   }
-  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;
+  TRY(writeBit(data.writeBit));
+  return data;
 }
 
 const error_category & OneWireMaster::errorCategory() {
@@ -118,10 +109,8 @@
 
       case InvalidLevelError:
         return "Invalid Level Error";
-
-      default:
-        return defaultErrorMessage(condition);
       }
+      return defaultErrorMessage(condition);
     }
   } instance;
   return instance;
--- a/MaximInterfaceCore/OneWireMaster.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/OneWireMaster.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,11 +30,12 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_OneWireMaster
-#define MaximInterfaceCore_OneWireMaster
+#ifndef MaximInterfaceCore_OneWireMaster_hpp
+#define MaximInterfaceCore_OneWireMaster_hpp
 
 #include <stdint.h>
 #include "Config.hpp"
+#include "Result.hpp"
 #include "span.hpp"
 #include "system_error.hpp"
 
@@ -57,10 +58,11 @@
     InvalidLevelError
   };
 
+  /// Result of the 1-Wire triplet command.
   struct TripletData {
-    bool writeBit;
     bool readBit;
     bool readBitComplement;
+    bool writeBit;
   };
 
   virtual ~OneWireMaster() {}
@@ -69,114 +71,108 @@
   /// 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;
+  virtual Result<void> 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 sendBit Bit to send on the 1-Wire bus.
   /// @param afterLevel Level to set the 1-Wire bus to after communication.
-  virtual error_code touchBitSetLevel(bool & sendRecvBit, Level afterLevel) = 0;
+  /// @returns Bit received from the 1-Wire bus.
+  virtual Result<bool> touchBitSetLevel(bool sendBit, 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
+  MaximInterfaceCore_EXPORT virtual Result<void>
   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);
+  /// @returns Data received from the 1-Wire bus.
+  MaximInterfaceCore_EXPORT virtual Result<uint_least8_t>
+  readByteSetLevel(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
+  MaximInterfaceCore_EXPORT virtual Result<void>
   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
+  MaximInterfaceCore_EXPORT virtual Result<void>
   readBlock(span<uint_least8_t> recvBuf);
 
   /// Set the 1-Wire bus communication speed.
-  virtual error_code setSpeed(Speed newSpeed) = 0;
+  virtual Result<void> setSpeed(Speed newSpeed) = 0;
 
   /// Set the 1-Wire bus level.
-  virtual error_code setLevel(Level newLevel) = 0;
+  virtual Result<void> 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);
+  /// @param sendBit Bit to send in case both read bits are zero.
+  MaximInterfaceCore_EXPORT virtual Result<TripletData> triplet(bool sendBit);
 
   /// @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);
+  Result<void> writeBitSetLevel(bool sendBit, Level afterLevel) {
+    MaximInterfaceCore_TRY(touchBitSetLevel(sendBit, afterLevel));
+    return none;
   }
 
   /// @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);
+  /// @returns Received data from the 1-Wire bus.
+  Result<bool> readBitSetLevel(Level afterLevel) {
+    return touchBitSetLevel(1, afterLevel);
   }
 
   // Alternate forms of the read and write functions.
 
-  error_code touchBit(bool & sendRecvBit) {
-    return touchBitSetLevel(sendRecvBit, NormalLevel);
+  Result<bool> touchBit(bool sendBit) {
+    return touchBitSetLevel(sendBit, NormalLevel);
   }
 
-  error_code writeBit(bool sendBit) {
+  Result<void> writeBit(bool sendBit) {
     return writeBitSetLevel(sendBit, NormalLevel);
   }
 
-  error_code readBit(bool & recvBit) {
-    return readBitSetLevel(recvBit, NormalLevel);
-  }
+  Result<bool> readBit() { return readBitSetLevel(NormalLevel); }
 
-  error_code writeBitPower(bool sendBit) {
+  Result<void> writeBitPower(bool sendBit) {
     return writeBitSetLevel(sendBit, StrongLevel);
   }
 
-  error_code readBitPower(bool & recvBit) {
-    return readBitSetLevel(recvBit, StrongLevel);
-  }
+  Result<bool> readBitPower() { return readBitSetLevel(StrongLevel); }
 
-  error_code writeByte(uint_least8_t sendByte) {
+  Result<void> writeByte(uint_least8_t sendByte) {
     return writeByteSetLevel(sendByte, NormalLevel);
   }
 
-  error_code readByte(uint_least8_t & recvByte) {
-    return readByteSetLevel(recvByte, NormalLevel);
-  }
+  Result<uint_least8_t> readByte() { return readByteSetLevel(NormalLevel); }
 
-  error_code writeBytePower(uint_least8_t sendByte) {
+  Result<void> writeBytePower(uint_least8_t sendByte) {
     return writeByteSetLevel(sendByte, StrongLevel);
   }
 
-  error_code readBytePower(uint_least8_t & recvByte) {
-    return readByteSetLevel(recvByte, StrongLevel);
+  Result<uint_least8_t> readBytePower() {
+    return readByteSetLevel(StrongLevel);
   }
 
   MaximInterfaceCore_EXPORT static const error_category & errorCategory();
 };
 
+template <> struct is_error_code_enum<OneWireMaster::ErrorValue> : true_type {};
+
 inline error_code make_error_code(OneWireMaster::ErrorValue e) {
   return error_code(e, OneWireMaster::errorCategory());
 }
--- a/MaximInterfaceCore/OneWireMasterDecorator.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/OneWireMasterDecorator.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -34,42 +34,43 @@
 
 namespace MaximInterfaceCore {
 
-error_code OneWireMasterDecorator::reset() { return master->reset(); }
+Result<void> OneWireMasterDecorator::reset() { return master->reset(); }
 
-error_code OneWireMasterDecorator::touchBitSetLevel(bool & sendRecvBit,
-                                                    Level afterLevel) {
-  return master->touchBitSetLevel(sendRecvBit, afterLevel);
+Result<bool> OneWireMasterDecorator::touchBitSetLevel(bool sendBit,
+                                                      Level afterLevel) {
+  return master->touchBitSetLevel(sendBit, afterLevel);
 }
 
-error_code OneWireMasterDecorator::writeByteSetLevel(uint_least8_t sendByte,
-                                                     Level afterLevel) {
+Result<void> 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);
+Result<uint_least8_t>
+OneWireMasterDecorator::readByteSetLevel(Level afterLevel) {
+  return master->readByteSetLevel(afterLevel);
 }
 
-error_code
+Result<void>
 OneWireMasterDecorator::writeBlock(span<const uint_least8_t> sendBuf) {
   return master->writeBlock(sendBuf);
 }
 
-error_code OneWireMasterDecorator::readBlock(span<uint_least8_t> recvBuf) {
+Result<void> OneWireMasterDecorator::readBlock(span<uint_least8_t> recvBuf) {
   return master->readBlock(recvBuf);
 }
 
-error_code OneWireMasterDecorator::setSpeed(Speed newSpeed) {
+Result<void> OneWireMasterDecorator::setSpeed(Speed newSpeed) {
   return master->setSpeed(newSpeed);
 }
 
-error_code OneWireMasterDecorator::setLevel(Level newLevel) {
+Result<void> OneWireMasterDecorator::setLevel(Level newLevel) {
   return master->setLevel(newLevel);
 }
 
-error_code OneWireMasterDecorator::triplet(TripletData & data) {
-  return master->triplet(data);
+Result<OneWireMaster::TripletData>
+OneWireMasterDecorator::triplet(bool sendBit) {
+  return master->triplet(sendBit);
 }
 
 } // namespace MaximInterfaceCore
--- a/MaximInterfaceCore/OneWireMasterDecorator.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/OneWireMasterDecorator.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_OneWireMasterDecorator
-#define MaximInterfaceCore_OneWireMasterDecorator
+#ifndef MaximInterfaceCore_OneWireMasterDecorator_hpp
+#define MaximInterfaceCore_OneWireMasterDecorator_hpp
 
 #include "Config.hpp"
 #include "OneWireMaster.hpp"
@@ -45,28 +45,28 @@
 public:
   void setMaster(OneWireMaster & master) { this->master = &master; }
 
-  MaximInterfaceCore_EXPORT virtual error_code reset();
+  MaximInterfaceCore_EXPORT virtual Result<void> reset();
 
-  MaximInterfaceCore_EXPORT virtual error_code
-  touchBitSetLevel(bool & sendRecvBit, Level afterLevel);
+  MaximInterfaceCore_EXPORT virtual Result<bool>
+  touchBitSetLevel(bool sendBit, Level afterLevel);
 
-  MaximInterfaceCore_EXPORT virtual error_code
+  MaximInterfaceCore_EXPORT virtual Result<void>
   writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
 
-  MaximInterfaceCore_EXPORT virtual error_code
-  readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+  MaximInterfaceCore_EXPORT virtual Result<uint_least8_t>
+  readByteSetLevel(Level afterLevel);
 
-  MaximInterfaceCore_EXPORT virtual error_code
+  MaximInterfaceCore_EXPORT virtual Result<void>
   writeBlock(span<const uint_least8_t> sendBuf);
 
-  MaximInterfaceCore_EXPORT virtual error_code
+  MaximInterfaceCore_EXPORT virtual Result<void>
   readBlock(span<uint_least8_t> recvBuf);
 
-  MaximInterfaceCore_EXPORT virtual error_code setSpeed(Speed newSpeed);
+  MaximInterfaceCore_EXPORT virtual Result<void> setSpeed(Speed newSpeed);
 
-  MaximInterfaceCore_EXPORT virtual error_code setLevel(Level newLevel);
+  MaximInterfaceCore_EXPORT virtual Result<void> setLevel(Level newLevel);
 
-  MaximInterfaceCore_EXPORT virtual error_code triplet(TripletData & data);
+  MaximInterfaceCore_EXPORT virtual Result<TripletData> triplet(bool sendBit);
 
 private:
   OneWireMaster * master;
--- a/MaximInterfaceCore/Optional.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/Optional.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_Optional
-#define MaximInterfaceCore_Optional
+#ifndef MaximInterfaceCore_Optional_hpp
+#define MaximInterfaceCore_Optional_hpp
 
 #include "None.hpp"
 #include "SafeBool.hpp"
@@ -42,7 +42,7 @@
 
 namespace MaximInterfaceCore {
 
-/// @brief Optional value container similar to std::optional.
+/// @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.
@@ -66,11 +66,19 @@
     return *this;
   }
 
+  Optional & operator=(const T & value) {
+    value_ = value;
+    hasValue_ = true;
+    return *this;
+  }
+
   template <typename U> Optional & operator=(const Optional<U> & other) {
-    if (hasValue_ || other.hasValue()) {
-      value_ = other.value();
-      hasValue_ = other.hasValue();
-    }
+    assign(other);
+    return *this;
+  }
+
+  Optional & operator=(const Optional & other) {
+    assign(other);
     return *this;
   }
 
@@ -116,6 +124,13 @@
   }
 
 private:
+  template <typename U> void assign(const Optional<U> & other) {
+    if (hasValue_ || other.hasValue()) {
+      value_ = other.value();
+      hasValue_ = other.hasValue();
+    }
+  }
+
   T value_;
   bool hasValue_;
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MaximInterfaceCore/Result.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -0,0 +1,350 @@
+/*******************************************************************************
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade 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_Result_hpp
+#define MaximInterfaceCore_Result_hpp
+
+#include "None.hpp"
+#include "Optional.hpp"
+#include "SafeBool.hpp"
+#include "system_error.hpp"
+
+// Include for std::swap.
+#include <algorithm>
+#include <utility>
+
+namespace MaximInterfaceCore {
+
+/// @brief Expected value container that holds either a value or an error.
+/// @details
+/// Result can be used to multiplex errors and values returned from functions
+/// that may fail as an alternative to exceptions.
+/// @tparam T
+/// Must be void or meet the requirements for DefaultConstructible,
+/// CopyConstructible, and CopyAssignable.
+template <typename T> class Result {
+public:
+  typedef T value_type;
+
+  Result() : value_(), error_(), hasValue_(false) {}
+
+  Result(const T & value) : value_(value), error_(), hasValue_(true) {}
+
+  Result(const error_code & error)
+      : value_(), error_(error), hasValue_(false) {}
+
+  template <typename ErrorCodeEnum>
+  Result(ErrorCodeEnum error,
+         typename enable_if<is_error_code_enum<ErrorCodeEnum>::value>::type * =
+             NULL)
+      : value_(), error_(error), hasValue_(false) {}
+
+  template <typename U>
+  explicit Result(const Result<U> & other)
+      : value_(other.value()), error_(other.error()),
+        hasValue_(other.hasValue()) {}
+
+  Result & operator=(const T & value) {
+    value_ = value;
+    error_.clear();
+    hasValue_ = true;
+    return *this;
+  }
+
+  Result & operator=(const error_code & error) {
+    error_ = error;
+    clearValue();
+    return *this;
+  }
+
+  template <typename ErrorCodeEnum>
+  typename enable_if<is_error_code_enum<ErrorCodeEnum>::value, Result &>::type
+  operator=(ErrorCodeEnum error) {
+    error_ = error;
+    clearValue();
+    return *this;
+  }
+
+  template <typename U> Result & operator=(const Result<U> & other) {
+    assign(other);
+    return *this;
+  }
+
+  Result & operator=(const Result & other) {
+    assign(other);
+    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 Result &>(*this).value());
+  }
+
+  const error_code & error() const { return error_; }
+
+  error_code & error() {
+    return const_cast<error_code &>(static_cast<const Result &>(*this).error());
+  }
+
+  void swap(Result & other) {
+    using std::swap;
+    if (hasValue_ || other.hasValue_) {
+      swap(value_, other.value_);
+      swap(hasValue_, other.hasValue_);
+    }
+    swap(error_, other.error_);
+  }
+
+private:
+  void clearValue() {
+    if (hasValue_) {
+      hasValue_ = false;
+      value_ = T();
+    }
+  }
+
+  template <typename U> void assign(const Result<U> & other) {
+    if (hasValue_ || other.hasValue()) {
+      value_ = other.value();
+      hasValue_ = other.hasValue();
+    }
+    error_ = other.error();
+  }
+
+  T value_;
+  error_code error_;
+  bool hasValue_;
+};
+
+template <typename T> Result<T> makeResult(const T & value) { return value; }
+
+template <typename T> void swap(Result<T> & lhs, Result<T> & rhs) {
+  lhs.swap(rhs);
+}
+
+template <typename T, typename U>
+bool operator==(const Result<T> & lhs, const Result<U> & rhs) {
+  if (lhs.hasValue() != rhs.hasValue()) {
+    return false;
+  }
+  if (!lhs.hasValue()) {
+    return lhs.error() == rhs.error();
+  }
+  return lhs.value() == rhs.value();
+}
+
+template <typename T, typename U>
+bool operator!=(const Result<T> & lhs, const Result<U> & rhs) {
+  if (lhs.hasValue() != rhs.hasValue()) {
+    return true;
+  }
+  if (!lhs.hasValue()) {
+    return lhs.error() != rhs.error();
+  }
+  return lhs.value() != rhs.value();
+}
+
+template <typename T, typename U>
+typename enable_if<!is_error_code_enum<U>::value, bool>::type
+operator==(const Result<T> & exp, const U & value) {
+  return exp.hasValue() ? exp.value() == value : false;
+}
+
+template <typename T, typename U>
+typename enable_if<!is_error_code_enum<T>::value, bool>::type
+operator==(const T & value, const Result<U> & exp) {
+  return operator==(exp, value);
+}
+
+template <typename T, typename U>
+typename enable_if<!is_error_code_enum<U>::value, bool>::type
+operator!=(const Result<T> & exp, const U & value) {
+  return exp.hasValue() ? exp.value() != value : true;
+}
+
+template <typename T, typename U>
+typename enable_if<!is_error_code_enum<T>::value, bool>::type
+operator!=(const T & value, const Result<U> & exp) {
+  return operator!=(exp, value);
+}
+
+template <typename T>
+bool operator==(const Result<T> & exp, const error_code & error) {
+  return exp.hasValue() ? false : exp.error() == error;
+}
+
+template <typename T>
+bool operator==(const error_code & error, const Result<T> & exp) {
+  return operator==(exp, error);
+}
+
+template <typename T>
+bool operator!=(const Result<T> & exp, const error_code & error) {
+  return exp.hasValue() ? true : exp.error() != error;
+}
+
+template <typename T>
+bool operator!=(const error_code & error, const Result<T> & exp) {
+  return operator!=(exp, error);
+}
+
+// Specialization for void.
+template <> class Result<void> {
+public:
+  typedef void value_type;
+
+  Result() : error_(), hasValue_(false) {}
+
+  Result(None) : error_(), hasValue_(true) {}
+
+  Result(const error_code & error) : error_(error), hasValue_(false) {}
+
+  template <typename ErrorCodeEnum>
+  Result(ErrorCodeEnum error,
+         typename enable_if<is_error_code_enum<ErrorCodeEnum>::value>::type * =
+             NULL)
+      : error_(error), hasValue_(false) {}
+
+  bool hasValue() const { return hasValue_; }
+
+  operator SafeBool() const { return makeSafeBool(hasValue()); }
+
+  void value() const {}
+
+  const error_code & error() const { return error_; }
+
+  error_code & error() {
+    return const_cast<error_code &>(static_cast<const Result &>(*this).error());
+  }
+
+  void swap(Result & other) {
+    using std::swap;
+    swap(hasValue_, other.hasValue_);
+    swap(error_, other.error_);
+  }
+
+private:
+  error_code error_;
+  bool hasValue_;
+};
+
+inline Result<void> makeResult(None) { return none; }
+
+template <>
+inline bool operator==(const Result<void> & lhs, const Result<void> & rhs) {
+  if (lhs.hasValue() != rhs.hasValue()) {
+    return false;
+  }
+  if (!lhs.hasValue()) {
+    return lhs.error() == rhs.error();
+  }
+  return true;
+}
+
+template <>
+inline bool operator!=(const Result<void> & lhs, const Result<void> & rhs) {
+  if (lhs.hasValue() != rhs.hasValue()) {
+    return true;
+  }
+  if (!lhs.hasValue()) {
+    return lhs.error() != rhs.error();
+  }
+  return false;
+}
+
+template <> inline bool operator==(const Result<void> & exp, const None &) {
+  return exp.hasValue();
+}
+
+template <> inline bool operator==(const None &, const Result<void> & exp) {
+  return operator==(exp, none);
+}
+
+template <> inline bool operator!=(const Result<void> & exp, const None &) {
+  return !operator==(exp, none);
+}
+
+template <> inline bool operator!=(const None &, const Result<void> & exp) {
+  return operator!=(exp, none);
+}
+
+namespace detail {
+
+template <typename T> Optional<error_code> TRY_helper(const Result<T> & expr) {
+  Optional<error_code> error;
+  if (!expr) {
+    error = expr.error();
+  }
+  return error;
+}
+
+template <typename T, typename U>
+Optional<error_code> TRY_VALUE_helper(T & var, const Result<U> & expr) {
+  Optional<error_code> error;
+  if (expr) {
+    var = expr.value();
+  } else {
+    error = expr.error();
+  }
+  return error;
+}
+
+} // namespace detail
+} // namespace MaximInterfaceCore
+
+// clang-format off
+
+/// @brief
+/// Evaluates an expression returning a Result type by continuing execution if
+/// successful or returning the error to the calling function if unsuccessful.
+#define MaximInterfaceCore_TRY(expr)                                           \
+  if (const ::MaximInterfaceCore::Optional< ::MaximInterfaceCore::error_code>  \
+          MaximInterfaceCore_TRY_error =                                       \
+              ::MaximInterfaceCore::detail::TRY_helper(expr))                  \
+    return MaximInterfaceCore_TRY_error.value()
+
+/// @brief
+/// Evaluates an expression returning a non-void Result type by assigning the
+/// value to the specified variable if successful or returning the error to the
+/// calling function if unsuccessful.
+#define MaximInterfaceCore_TRY_VALUE(var, expr)                                \
+  if (const ::MaximInterfaceCore::Optional< ::MaximInterfaceCore::error_code>  \
+          MaximInterfaceCore_TRY_VALUE_error =                                 \
+              ::MaximInterfaceCore::detail::TRY_VALUE_helper(var, expr))       \
+    return MaximInterfaceCore_TRY_VALUE_error.value()
+
+#endif
--- a/MaximInterfaceCore/RomCommands.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/RomCommands.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -34,16 +34,6 @@
 
 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;
@@ -55,110 +45,112 @@
   }
 }
 
-error_code verifyRom(OneWireMaster & master, RomId::const_span romId) {
+Result<void> verifyRom(OneWireMaster & master, RomId::const_span romId) {
   SearchRomState searchState(romId);
-  error_code result = searchRom(master, searchState);
-  if (result) {
+  Result<void> 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);
+    result = OneWireMaster::NoSlaveError;
   }
   return result;
 }
 
-error_code readRom(OneWireMaster & master, RomId::span romId) {
-  error_code result = master.reset();
-  if (result) {
+Result<RomId::array> readRom(OneWireMaster & master) {
+  Result<void> result = master.reset();
+  if (!result) {
+    return result.error();
+  }
+  result = master.writeByte(0x33);
+  if (!result) {
+    return result.error();
+  }
+  RomId::array romId;
+  result = master.readBlock(romId);
+  if (!result) {
+    return result.error();
+  }
+  if (!valid(romId)) {
+    return OneWireMaster::NoSlaveError;
+  }
+  return romId;
+}
+
+Result<void> skipRom(OneWireMaster & master) {
+  Result<void> 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);
-  }
+  result = master.writeByte(0xCC);
   return result;
 }
 
-error_code skipRom(OneWireMaster & master) {
-  error_code result = master.reset();
-  if (result) {
+Result<void> matchRom(OneWireMaster & master, RomId::const_span romId) {
+  Result<void> 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) {
+  result = master.writeByte(0x55);
+  if (!result) {
     return result;
   }
   result = master.writeBlock(romId);
   return result;
 }
 
-error_code overdriveSkipRom(OneWireMaster & master) {
-  error_code result = master.reset();
-  if (result) {
+Result<void> overdriveSkipRom(OneWireMaster & master) {
+  Result<void> result = master.reset();
+  if (!result) {
     return result;
   }
-  result = master.writeByte(OverdriveSkipRomCmd);
-  if (result) {
+  result = master.writeByte(0x3C);
+  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) {
+Result<void> overdriveMatchRom(OneWireMaster & master,
+                               RomId::const_span romId) {
+  Result<void> result = master.reset();
+  if (!result) {
     return result;
   }
-  result = master.writeByte(OverdriveMatchRomCmd);
-  if (result) {
+  result = master.writeByte(0x69);
+  if (!result) {
     return result;
   }
   result = master.setSpeed(OneWireMaster::OverdriveSpeed);
-  if (result) {
+  if (!result) {
     return result;
   }
   result = master.writeBlock(romId);
   return result;
 }
 
-error_code resumeRom(OneWireMaster & master) {
-  error_code result = master.reset();
-  if (result) {
+Result<void> resumeRom(OneWireMaster & master) {
+  Result<void> result = master.reset();
+  if (!result) {
     return result;
   }
-  result = master.writeByte(ResumeRomCmd);
+  result = master.writeByte(0xA5);
   return result;
 }
 
-error_code searchRom(OneWireMaster & master, SearchRomState & searchState) {
+Result<void> searchRom(OneWireMaster & master, SearchRomState & searchState) {
   if (searchState.lastDevice) {
     searchState = SearchRomState();
   }
 
-  error_code result = master.reset();
-  if (result) {
+  Result<void> result = master.reset();
+  if (!result) {
     return result;
   }
-  result = master.writeByte(SearchRomCmd);
-  if (result) {
+  result = master.writeByte(0xF0);
+  if (!result) {
     return result;
   }
 
@@ -178,12 +170,10 @@
           (searchState.romId[idByteNumber] & idBitMask) == idBitMask;
     }
 
-    result = master.triplet(tripletData);
-    if (result) {
-      return result;
-    }
+    MaximInterfaceCore_TRY_VALUE(tripletData,
+                                 master.triplet(tripletData.writeBit));
     if (tripletData.readBit && tripletData.readBitComplement) {
-      return make_error_code(OneWireMaster::NoSlaveError);
+      return OneWireMaster::NoSlaveError;
     }
 
     if (tripletData.writeBit) {
@@ -202,7 +192,7 @@
     }
     searchState = newSearchState;
   } else {
-    result = make_error_code(OneWireMaster::NoSlaveError);
+    result = OneWireMaster::NoSlaveError;
   }
   return result;
 }
--- a/MaximInterfaceCore/RomCommands.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/RomCommands.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -33,8 +33,8 @@
 /// @file
 /// @brief ROM Commands for enumerating and selecting 1-Wire devices.
 
-#ifndef MaximInterfaceCore_RomCommands
-#define MaximInterfaceCore_RomCommands
+#ifndef MaximInterfaceCore_RomCommands_hpp
+#define MaximInterfaceCore_RomCommands_hpp
 
 #include <stdint.h>
 #include "Algorithm.hpp"
@@ -63,7 +63,7 @@
   explicit SearchRomState(RomId::element familyCode)
       : romId(), lastDiscrepancy(64), lastFamilyDiscrepancy(0),
         lastDevice(false) {
-    setFamilyCode(romId, familyCode);
+    romId.front() = familyCode;
   }
 };
 
@@ -73,23 +73,22 @@
 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);
+MaximInterfaceCore_EXPORT Result<void> 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);
+/// @returns ROM ID read from device.
+MaximInterfaceCore_EXPORT Result<RomId::array> readRom(OneWireMaster & master);
 
 /// @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);
+MaximInterfaceCore_EXPORT Result<void> skipRom(OneWireMaster & master);
 
 /// @brief Use the Match ROM command to select the device by its known ID.
 /// @note
@@ -97,8 +96,8 @@
 /// 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);
+MaximInterfaceCore_EXPORT Result<void> matchRom(OneWireMaster & master,
+                                                RomId::const_span romId);
 
 /// @brief Issue Overdrive Skip ROM command on bus.
 /// @note
@@ -107,20 +106,20 @@
 /// @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);
+MaximInterfaceCore_EXPORT Result<void> 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);
+MaximInterfaceCore_EXPORT Result<void>
+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);
+MaximInterfaceCore_EXPORT Result<void> resumeRom(OneWireMaster & master);
 
 /// @brief Find device on the 1-Wire bus.
 /// @details
@@ -128,8 +127,8 @@
 /// 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);
+MaximInterfaceCore_EXPORT Result<void> searchRom(OneWireMaster & master,
+                                                 SearchRomState & searchState);
 
 } // namespace MaximInterfaceCore
 
--- a/MaximInterfaceCore/RomId.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/RomId.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,49 +30,21 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_RomId
-#define MaximInterfaceCore_RomId
+#ifndef MaximInterfaceCore_RomId_hpp
+#define MaximInterfaceCore_RomId_hpp
 
 #include "array_span.hpp"
-#include "crc.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);
+  return calculateCrc8(romId.first(romId.size() - 1)) == romId.back();
 }
 
 } // namespace MaximInterfaceCore
--- a/MaximInterfaceCore/RunCommand.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/RunCommand.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 * ownership rights.
 *******************************************************************************/
 
-#include "crc.hpp"
+#include "Crc.hpp"
 #include "Error.hpp"
 #include "I2CMaster.hpp"
 #include "OneWireMaster.hpp"
@@ -58,37 +58,37 @@
   return instance;
 }
 
-error_code RunCommandWithOneWireMaster::
+Result<span<uint_least8_t> > RunCommandWithOneWireMaster::
 operator()(span<const uint_least8_t> request, int delayTime,
-           span<uint_least8_t> & response) const {
+           span<uint_least8_t> response) const {
   // Write request.
-  error_code result = selectRom(*master);
-  if (result) {
-    return result;
+  Result<void> result = selectRom(*master);
+  if (!result) {
+    return result.error();
   }
   uint_least8_t xpcBuffer[2] = {0x66,
                                 static_cast<uint_least8_t>(request.size())};
   result = master->writeBlock(xpcBuffer);
-  if (result) {
-    return result;
+  if (!result) {
+    return result.error();
   }
   result = master->writeBlock(request);
-  if (result) {
-    return result;
+  if (!result) {
+    return result.error();
   }
   uint_fast16_t expectedCrc =
       calculateCrc16(calculateCrc16(xpcBuffer), request) ^ 0xFFFFu;
   result = master->readBlock(xpcBuffer);
-  if (result) {
-    return result;
+  if (!result) {
+    return result.error();
   }
   if (expectedCrc !=
       ((static_cast<uint_fast16_t>(xpcBuffer[1]) << 8) | xpcBuffer[0])) {
-    return make_error_code(CrcError);
+    return CrcError;
   }
   result = master->writeBytePower(0xAA);
-  if (result) {
-    return result;
+  if (!result) {
+    return result.error();
   }
 
   // Wait for device to process.
@@ -96,33 +96,33 @@
 
   // Read response.
   result = master->setLevel(OneWireMaster::NormalLevel);
-  if (result) {
-    return result;
+  if (!result) {
+    return result.error();
   }
   result = master->readBlock(xpcBuffer);
-  if (result) {
-    return result;
+  if (!result) {
+    return result.error();
   }
   if (xpcBuffer[1] > response.size()) {
-    return make_error_code(InvalidResponseError);
+    return InvalidResponseError;
   }
   response = response.first(xpcBuffer[1]);
   result = master->readBlock(response);
-  if (result) {
-    return result;
+  if (!result) {
+    return result.error();
   }
   expectedCrc =
       calculateCrc16(calculateCrc16(make_span(xpcBuffer + 1, 1)), response) ^
       0xFFFFu;
   result = master->readBlock(xpcBuffer);
-  if (result) {
-    return result;
+  if (!result) {
+    return result.error();
   }
   if (expectedCrc !=
       ((static_cast<uint_fast16_t>(xpcBuffer[1]) << 8) | xpcBuffer[0])) {
-    return make_error_code(CrcError);
+    return CrcError;
   }
-  return result;
+  return response;
 }
 
 const error_category & RunCommandWithI2CMaster::errorCategory() {
@@ -141,41 +141,42 @@
   return instance;
 }
 
-error_code RunCommandWithI2CMaster::
+Result<span<uint_least8_t> > RunCommandWithI2CMaster::
 operator()(span<const uint_least8_t> request, int delayTime,
-           span<uint_least8_t> & response) const {
+           span<uint_least8_t> response) const {
   // Write request.
-  error_code result = master->start(address_);
-  if (result == make_error_condition(I2CMaster::NackError) && address_ != 0) {
+  Result<void> result = master->start(address_);
+  if (!result && result.error() == make_error_condition(I2CMaster::NackError) &&
+      address_ != 0) {
     result = master->start(0);
   }
-  if (result) {
+  if (!result) {
     master->stop();
-    return result;
+    return result.error();
   }
   if (!request.empty()) {
     result = master->writeByte(request[0]);
-    if (result) {
+    if (!result) {
       master->stop();
-      return result;
+      return result.error();
     }
     request = request.subspan(1);
     if (!request.empty()) {
       result = master->writeByte(static_cast<uint_least8_t>(request.size()));
-      if (result) {
+      if (!result) {
         master->stop();
-        return result;
+        return result.error();
       }
       result = master->writeBlock(request);
-      if (result) {
+      if (!result) {
         master->stop();
-        return result;
+        return result.error();
       }
     }
   }
   result = master->stop();
-  if (result) {
-    return result;
+  if (!result) {
+    return result.error();
   }
 
   // Wait for device to process.
@@ -183,28 +184,32 @@
 
   // Read response.
   result = master->start(address_ | 1);
-  if (result) {
+  if (!result) {
     master->stop();
-    return result;
+    return result.error();
   }
   uint_least8_t length;
-  result = master->readByte(I2CMaster::Ack, length);
-  if (result) {
+  if (const Result<uint_least8_t> result = master->readByte(I2CMaster::Ack)) {
+    length = result.value();
+  } else {
     master->stop();
-    return result;
+    return result.error();
   }
   if (length > response.size()) {
     master->stop();
-    return make_error_code(InvalidResponseError);
+    return InvalidResponseError;
   }
   response = response.first(length);
-  result = master->readBlock(I2CMaster::Nack, response);
-  if (result) {
+  result = master->readBlock(response, I2CMaster::Nack);
+  if (!result) {
     master->stop();
-    return result;
+    return result.error();
   }
   result = master->stop();
-  return result;
+  if (!result) {
+    return result.error();
+  }
+  return response;
 }
 
 } // namespace MaximInterfaceCore
--- a/MaximInterfaceCore/RunCommand.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/RunCommand.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_RunCommand
-#define MaximInterfaceCore_RunCommand
+#ifndef MaximInterfaceCore_RunCommand_hpp
+#define MaximInterfaceCore_RunCommand_hpp
 
 #include "Config.hpp"
 #include "Function.hpp"
@@ -45,8 +45,15 @@
 class OneWireMaster;
 class Sleep;
 
-typedef Function<error_code(span<const uint_least8_t>, int,
-                            span<uint_least8_t> &)>
+/// @brief
+/// Runs a command sequence by writing the command request, waiting the
+/// specified amount of time, and reading back the command response.
+/// @details
+/// The parameters for this function are the command request, the delay time in
+/// milliseconds, and a mutable buffer for the command response. The actual
+/// buffer used for the command response is returned.
+typedef Function<Result<span<uint_least8_t> >(span<const uint_least8_t>, int,
+                                              span<uint_least8_t>)>
     RunCommand;
 
 class RunCommandWithOneWireMaster {
@@ -68,9 +75,9 @@
     this->selectRom = selectRom;
   }
 
-  MaximInterfaceCore_EXPORT error_code
+  MaximInterfaceCore_EXPORT Result<span<uint_least8_t> >
   operator()(span<const uint_least8_t> request, int delayTime,
-             span<uint_least8_t> & response) const;
+             span<uint_least8_t> response) const;
 
 private:
   SelectRom selectRom;
@@ -78,6 +85,10 @@
   const Sleep * sleep;
 };
 
+template <>
+struct is_error_code_enum<RunCommandWithOneWireMaster::ErrorValue>
+    : true_type {};
+
 inline error_code make_error_code(RunCommandWithOneWireMaster::ErrorValue e) {
   return error_code(e, RunCommandWithOneWireMaster::errorCategory());
 }
@@ -101,9 +112,9 @@
 
   void setAddress(uint_least8_t address) { address_ = address & 0xFE; }
 
-  MaximInterfaceCore_EXPORT error_code
+  MaximInterfaceCore_EXPORT Result<span<uint_least8_t> >
   operator()(span<const uint_least8_t> request, int delayTime,
-             span<uint_least8_t> & response) const;
+             span<uint_least8_t> response) const;
 
 private:
   const Sleep * sleep;
@@ -111,6 +122,9 @@
   uint_least8_t address_;
 };
 
+template <>
+struct is_error_code_enum<RunCommandWithI2CMaster::ErrorValue> : true_type {};
+
 inline error_code make_error_code(RunCommandWithI2CMaster::ErrorValue e) {
   return error_code(e, RunCommandWithI2CMaster::errorCategory());
 }
--- a/MaximInterfaceCore/SafeBool.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/SafeBool.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_SafeBool
-#define MaximInterfaceCore_SafeBool
+#ifndef MaximInterfaceCore_SafeBool_hpp
+#define MaximInterfaceCore_SafeBool_hpp
 
 #include <stddef.h>
 #include "Unconstructible.hpp"
--- a/MaximInterfaceCore/Segment.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ /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 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
--- a/MaximInterfaceCore/SelectRom.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/SelectRom.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -34,19 +34,12 @@
 
 namespace MaximInterfaceCore {
 
-error_code SelectMatchRom::operator()(OneWireMaster & master) const {
+SelectMatchRom::SelectMatchRom(RomId::const_span romId) {
+  copy(romId, make_span(romId_));
+}
+
+Result<void> 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
--- a/MaximInterfaceCore/SelectRom.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/SelectRom.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,21 +30,20 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_SelectRom
-#define MaximInterfaceCore_SelectRom
+#ifndef MaximInterfaceCore_SelectRom_hpp
+#define MaximInterfaceCore_SelectRom_hpp
 
 #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;
+typedef Function<Result<void>(OneWireMaster &)> SelectRom;
 
 /// Selector for a multidrop 1-Wire bus.
 class SelectMatchRom {
@@ -52,49 +51,15 @@
   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_; }
+  explicit SelectMatchRom(RomId::const_span romId);
 
-  void setRomId(RomId::const_span romId) { copy(romId, make_span(romId_)); }
-
-  MaximInterfaceCore_EXPORT error_code operator()(OneWireMaster & master) const;
+  MaximInterfaceCore_EXPORT Result<void>
+  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
--- a/MaximInterfaceCore/SerialPort.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/SerialPort.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_SerialPort
-#define MaximInterfaceCore_SerialPort
+#ifndef MaximInterfaceCore_SerialPort_hpp
+#define MaximInterfaceCore_SerialPort_hpp
 
 #include <string>
 #include "Uart.hpp"
@@ -41,17 +41,10 @@
 class SerialPort : public Uart {
 public:
   /// Connect a specified COM port.
-  virtual error_code connect(const std::string & portName) = 0;
+  virtual Result<void> 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;
+  virtual Result<void> disconnect() = 0;
 };
 
 } // namespace MaximInterfaceCore
--- a/MaximInterfaceCore/Sleep.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/Sleep.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_Sleep
-#define MaximInterfaceCore_Sleep
+#ifndef MaximInterfaceCore_Sleep_hpp
+#define MaximInterfaceCore_Sleep_hpp
 
 namespace MaximInterfaceCore {
 
--- a/MaximInterfaceCore/SleepDecorator.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/SleepDecorator.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
--- a/MaximInterfaceCore/SleepDecorator.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/SleepDecorator.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_SleepDecorator
-#define MaximInterfaceCore_SleepDecorator
+#ifndef MaximInterfaceCore_SleepDecorator_hpp
+#define MaximInterfaceCore_SleepDecorator_hpp
 
 #include "Config.hpp"
 #include "Sleep.hpp"
--- a/MaximInterfaceCore/Uart.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/Uart.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -35,21 +35,18 @@
 
 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]);
+Result<void> Uart::writeBlock(span<const uint_least8_t> data) {
+  for (span<const uint_least8_t>::index_type i = 0; i < data.size(); ++i) {
+    MaximInterfaceCore_TRY(writeByte(data[i]));
   }
-  return result;
+  return none;
 }
 
-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]);
+Result<void> Uart::readBlock(span<uint_least8_t> data) {
+  for (span<uint_least8_t>::index_type i = 0; i < data.size(); ++i) {
+    MaximInterfaceCore_TRY_VALUE(data[i], readByte());
   }
-  return result;
+  return none;
 }
 
 const error_category & Uart::errorCategory() {
@@ -64,10 +61,8 @@
 
       case OverrunError:
         return "Overrun Error";
-
-      default:
-        return defaultErrorMessage(condition);
       }
+      return defaultErrorMessage(condition);
     }
   } instance;
   return instance;
--- a/MaximInterfaceCore/Uart.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/Uart.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,11 +30,12 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_Uart
-#define MaximInterfaceCore_Uart
+#ifndef MaximInterfaceCore_Uart_hpp
+#define MaximInterfaceCore_Uart_hpp
 
 #include <stdint.h>
 #include "Config.hpp"
+#include "Result.hpp"
 #include "span.hpp"
 #include "system_error.hpp"
 
@@ -51,37 +52,39 @@
   virtual ~Uart() {}
 
   /// Set the baud rate of the port in Hz.
-  virtual error_code setBaudRate(int_least32_t baudRate) = 0;
+  virtual Result<void> setBaudRate(int_least32_t baudRate) = 0;
 
   /// Generate a break condition on the port for a small amount of time.
-  virtual error_code sendBreak() = 0;
+  virtual Result<void> sendBreak() = 0;
 
   /// Clear all received data that was buffered.
-  virtual error_code clearReadBuffer() = 0;
+  virtual Result<void> clearReadBuffer() = 0;
 
   /// Writes a byte of data to the port.
-  virtual error_code writeByte(uint_least8_t data) = 0;
+  virtual Result<void> writeByte(uint_least8_t data) = 0;
 
   /// Writes a block of data to the port.
-  MaximInterfaceCore_EXPORT virtual error_code
+  MaximInterfaceCore_EXPORT virtual Result<void>
   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;
+  /// @returns Data read from the port if successful.
+  virtual Result<uint_least8_t> readByte() = 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
+  MaximInterfaceCore_EXPORT virtual Result<void>
   readBlock(span<uint_least8_t> data);
 
   MaximInterfaceCore_EXPORT static const error_category & errorCategory();
 };
 
+template <> struct is_error_code_enum<Uart::ErrorValue> : true_type {};
+
 inline error_code make_error_code(Uart::ErrorValue e) {
   return error_code(e, Uart::errorCategory());
 }
--- a/MaximInterfaceCore/Unconstructible.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/Unconstructible.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2019 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_Unconstructible
-#define MaximInterfaceCore_Unconstructible
+#ifndef MaximInterfaceCore_Unconstructible_hpp
+#define MaximInterfaceCore_Unconstructible_hpp
 
 namespace MaximInterfaceCore {
 
--- a/MaximInterfaceCore/Uncopyable.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/Uncopyable.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_Uncopyable
-#define MaximInterfaceCore_Uncopyable
+#ifndef MaximInterfaceCore_Uncopyable_hpp
+#define MaximInterfaceCore_Uncopyable_hpp
 
 namespace MaximInterfaceCore {
 
--- a/MaximInterfaceCore/WriteMessage.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/WriteMessage.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_WriteMessage
-#define MaximInterfaceCore_WriteMessage
+#ifndef MaximInterfaceCore_WriteMessage_hpp
+#define MaximInterfaceCore_WriteMessage_hpp
 
 #include <string>
 #include "Function.hpp"
--- a/MaximInterfaceCore/array.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/array.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_array
-#define MaximInterfaceCore_array
+#ifndef MaximInterfaceCore_array_hpp
+#define MaximInterfaceCore_array_hpp
 
 #include <stddef.h>
 #include <stdint.h>
@@ -131,9 +131,6 @@
 
   static size_type max_size() { return size(); }
 
-  /// Alternative to size() when a constant expression is required.
-  static const size_type csize = N;
-
   /// @}
 
   /// @name Operations
--- a/MaximInterfaceCore/array_span.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/array_span.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_array_span
-#define MaximInterfaceCore_array_span
+#ifndef MaximInterfaceCore_array_span_hpp
+#define MaximInterfaceCore_array_span_hpp
 
 #include "array.hpp"
 #include "span.hpp"
@@ -53,6 +53,8 @@
   typedef MaximInterfaceCore::span<T, N> span;
 };
 
+template <typename T, size_t N> const size_t array_span<T, N>::size;
+
 // Specialization for "const T" is not defined.
 template <typename T, size_t N> struct array_span<const T, N>;
 
--- a/MaximInterfaceCore/crc.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/crc.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,7 +30,7 @@
 * ownership rights.
 *******************************************************************************/
 
-#include "crc.hpp"
+#include "Crc.hpp"
 
 namespace MaximInterfaceCore {
 
--- a/MaximInterfaceCore/crc.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/crc.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_crc
-#define MaximInterfaceCore_crc
+#ifndef MaximInterfaceCore_Crc_hpp
+#define MaximInterfaceCore_Crc_hpp
 
 #include <stddef.h>
 #include <stdint.h>
--- a/MaximInterfaceCore/span.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/span.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,11 +30,10 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_span
-#define MaximInterfaceCore_span
+#ifndef MaximInterfaceCore_span_hpp
+#define MaximInterfaceCore_span_hpp
 
 #include <stddef.h>
-#include <stdint.h>
 #include <iterator>
 #include <vector>
 #include "array.hpp"
@@ -43,7 +42,7 @@
 namespace MaximInterfaceCore {
 
 /// Differentiates spans of static and dynamic extent.
-static const size_t dynamic_extent = SIZE_MAX;
+static const size_t dynamic_extent = static_cast<size_t>(-1); // SIZE_MAX
 
 /// @brief
 /// Generic memory span class similar to gsl::span and the proposed std::span.
@@ -155,11 +154,60 @@
   pointer data_;
 };
 
-template <typename T> struct is_array : false_type {};
+template <template <typename, size_t> class span, typename T, size_t Extent>
+const typename span_base<span, T, Extent>::index_type
+    span_base<span, T, Extent>::extent;
+
+template <typename T> class has_data {
+  typedef char true_type[1];
+  typedef char false_type[2];
+
+  template <typename U, U> struct check;
+
+  template <typename U>
+  static true_type & test(check<typename U::pointer (U::*)(), &U::data> *);
+
+  template <typename> static false_type & test(...);
+
+public:
+  static const bool value = (sizeof(test<T>(NULL)) == sizeof(true_type));
+};
+
+template <typename T> class has_data<const T> {
+  typedef char true_type[1];
+  typedef char false_type[2];
+
+  template <typename U, U> struct check;
 
-template <typename T> struct is_array<T[]> : true_type {};
+  template <typename U>
+  static true_type &
+  test(check<typename U::const_pointer (U::*)() const, &U::data> *);
+
+  template <typename> static false_type & test(...);
+
+public:
+  static const bool value = (sizeof(test<T>(NULL)) == sizeof(true_type));
+};
+
+template <typename T> class has_size {
+  typedef char true_type[1];
+  typedef char false_type[2];
 
-template <typename T, size_t N> struct is_array<T[N]> : true_type {};
+  template <typename U, U> struct check;
+
+  template <typename U>
+  static true_type &
+  test(check<typename U::size_type (U::*)() const, &U::size> *);
+
+  // Additionally support a static member function.
+  template <typename U>
+  static true_type & test(check<typename U::size_type (*)(), &U::size> *);
+
+  template <typename> static false_type & test(...);
+
+public:
+  static const bool value = (sizeof(test<T>(NULL)) == sizeof(true_type));
+};
 
 template <typename T> struct is_array_class_helper : false_type {};
 
@@ -185,16 +233,11 @@
 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.
+// Used to disable the span 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 ||
+struct enable_if_span_convertible
+    : enable_if<has_data<T>::value && has_size<T>::value &&
+                !(is_array_class<T>::value || is_span<T>::value ||
                   is_vector<T>::value)> {};
 
 } // namespace detail
@@ -232,13 +275,12 @@
 
   template <typename Container>
   span(Container & cont,
-       typename detail::enable_if_static_extent_convertible<Container>::type * =
-           NULL)
+       typename detail::enable_if_span_convertible<Container>::type * = NULL)
       : span_base(cont.data()) {}
 
   template <typename Container>
   span(const Container & cont,
-       typename detail::enable_if_static_extent_convertible<Container>::type * =
+       typename detail::enable_if_span_convertible<const Container>::type * =
            NULL)
       : span_base(cont.data()) {}
 
@@ -284,6 +326,12 @@
 
   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, size_t N>
   span(const span<U, N> & s) : span_base(s.data()), size_(s.size()) {}
 
@@ -296,17 +344,14 @@
       : 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(Container & cont,
+       typename detail::enable_if_span_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(const Container & cont,
+       typename detail::enable_if_span_convertible<const Container>::type * =
+           NULL)
       : span_base(cont.data()), size_(cont.size()) {}
 
   /// @name Observers
--- a/MaximInterfaceCore/system_error.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/system_error.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
--- a/MaximInterfaceCore/system_error.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/system_error.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -35,13 +35,15 @@
 /// Error handling constructs similar to std::error_code, std::error_condition,
 /// and std::error_category.
 
-#ifndef MaximInterfaceCore_system_error
-#define MaximInterfaceCore_system_error
+#ifndef MaximInterfaceCore_system_error_hpp
+#define MaximInterfaceCore_system_error_hpp
 
+#include <stddef.h>
 #include <stdexcept>
 #include <string>
 #include "Config.hpp"
 #include "SafeBool.hpp"
+#include "type_traits.hpp"
 #include "Uncopyable.hpp"
 
 namespace MaximInterfaceCore {
@@ -49,6 +51,7 @@
 class error_condition;
 class error_code;
 
+/// Error category interface.
 class error_category : private Uncopyable {
 public:
   virtual ~error_category() {}
@@ -79,8 +82,15 @@
   return &lhs < &rhs;
 }
 
+/// Default error category.
 MaximInterfaceCore_EXPORT const error_category & system_category();
 
+/// Checks if an enum type is implicitly convertible to an error_condition.
+template <typename T> struct is_error_condition_enum : false_type {};
+
+/// @brief
+/// Used for classifying groups of error_code into higher-level error conditions
+/// through the error_category::equivalent methods.
 class error_condition {
 public:
   error_condition() : value_(0), category_(&system_category()) {}
@@ -88,6 +98,22 @@
   error_condition(int value, const error_category & category)
       : value_(value), category_(&category) {}
 
+  template <typename ErrorConditionEnum>
+  error_condition(
+      ErrorConditionEnum e,
+      typename enable_if<
+          is_error_condition_enum<ErrorConditionEnum>::value>::type * = NULL) {
+    *this = make_error_condition(e);
+  }
+
+  template <typename ErrorConditionEnum>
+  typename enable_if<is_error_condition_enum<ErrorConditionEnum>::value,
+                     error_condition &>::type
+  operator=(ErrorConditionEnum e) {
+    *this = make_error_condition(e);
+    return *this;
+  }
+
   void assign(int value, const error_category & category) {
     value_ = value;
     category_ = &category;
@@ -127,6 +153,15 @@
          ((lhs.category() == rhs.category()) && (lhs.value() < rhs.value()));
 }
 
+/// Checks if an enum type is implicitly convertible to an error_code.
+template <typename T> struct is_error_code_enum : false_type {};
+
+/// @brief Holds a raw error code produced by a subsystem.
+/// @details
+/// An error_code is composed of a pair of values: a category of errors, usually
+/// one per subsystem, and a number representing a specific error value within
+/// that category. While not required, zero is typically used as the success
+/// value so that the boolean conversion can be used as a failure test.
 class error_code {
 public:
   error_code() : value_(0), category_(&system_category()) {}
@@ -134,6 +169,22 @@
   error_code(int value, const error_category & category)
       : value_(value), category_(&category) {}
 
+  template <typename ErrorCodeEnum>
+  error_code(
+      ErrorCodeEnum e,
+      typename enable_if<is_error_code_enum<ErrorCodeEnum>::value>::type * =
+          NULL) {
+    *this = make_error_code(e);
+  }
+
+  template <typename ErrorCodeEnum>
+  typename enable_if<is_error_code_enum<ErrorCodeEnum>::value,
+                     error_code &>::type
+  operator=(ErrorCodeEnum e) {
+    *this = make_error_code(e);
+    return *this;
+  }
+
   void assign(int value, const error_category & category) {
     value_ = value;
     category_ = &category;
@@ -198,6 +249,7 @@
   return !operator==(lhs, rhs);
 }
 
+/// Wrapper for throwing error_code as an exception.
 class system_error : public std::runtime_error {
 public:
   MaximInterfaceCore_EXPORT system_error(const error_code & ec);
--- a/MaximInterfaceCore/type_traits.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceCore/type_traits.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceCore_type_traits
-#define MaximInterfaceCore_type_traits
+#ifndef MaximInterfaceCore_type_traits_hpp
+#define MaximInterfaceCore_type_traits_hpp
 
 namespace MaximInterfaceCore {
 
@@ -43,6 +43,8 @@
   value_type operator()() const { return value; }
 };
 
+template <typename T, T v> const T integral_constant<T, v>::value;
+
 typedef integral_constant<bool, true> true_type;
 typedef integral_constant<bool, false> false_type;
 
--- a/MaximInterfaceDevices/Config.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/Config.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2019 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
--- a/MaximInterfaceDevices/DS18B20.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS18B20.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -34,6 +34,9 @@
 #include <MaximInterfaceCore/OneWireMaster.hpp>
 #include "DS18B20.hpp"
 
+#define TRY MaximInterfaceCore_TRY
+#define TRY_VALUE MaximInterfaceCore_TRY_VALUE
+
 namespace MaximInterfaceDevices {
 
 using namespace Core;
@@ -43,85 +46,80 @@
 const uint_least8_t DS18B20::elevenBitResolution;
 const uint_least8_t DS18B20::twelveBitResolution;
 
-error_code DS18B20::initialize() {
-  Scratchpad::array scratchpad;
-  return readScratchpad(scratchpad);
+Result<void> DS18B20::initialize() const {
+  TRY(readScratchpad());
+  return none;
 }
 
-error_code DS18B20::writeScratchpad(uint_least8_t th, uint_least8_t tl,
-                                    uint_least8_t res) {
-  error_code result = selectRom(*master);
-  if (!result) {
+Result<void> DS18B20::writeScratchpad(uint_least8_t th, uint_least8_t tl,
+                                      uint_least8_t res) {
+  Result<void> result = selectRom(*master);
+  if (result) {
     const uint_least8_t sendBlock[] = {0x4E, th, tl, res};
     result = master->writeBlock(sendBlock);
-    if (!result) {
+    if (result) {
       resolution = res;
     }
   }
   return result;
 }
 
-error_code DS18B20::readScratchpad(Scratchpad::span scratchpad) {
-  error_code result = selectRom(*master);
-  if (result) {
-    return result;
+Result<DS18B20::Scratchpad> DS18B20::readScratchpad() const {
+  Result<void> result = selectRom(*master);
+  if (!result) {
+    return result.error();
   }
   result = master->writeByte(0xBE);
-  if (result) {
-    return result;
+  if (!result) {
+    return result.error();
   }
+  Scratchpad scratchpad;
   result = master->readBlock(scratchpad);
-  if (result) {
-    return result;
+  if (!result) {
+    return result.error();
   }
   uint_least8_t receivedCrc;
-  result = master->readByte(receivedCrc);
-  if (result) {
-    return result;
+  TRY_VALUE(receivedCrc, master->readByte());
+  if (receivedCrc != calculateCrc8(scratchpad)) {
+    return CrcError;
   }
-  if (receivedCrc == calculateCrc8(scratchpad)) {
-    resolution = scratchpad[4];
-  } else {
-    result = make_error_code(CrcError);
-  }
-  return result;
+  resolution = scratchpad[4];
+  return scratchpad;
 }
 
-error_code DS18B20::readPowerSupply(bool & localPower) {
-  error_code result = selectRom(*master);
-  if (result) {
-    return result;
+Result<bool> DS18B20::readPowerSupply() const {
+  Result<void> result = selectRom(*master);
+  if (!result) {
+    return result.error();
   }
   result = master->writeByte(0xB4);
-  if (result) {
-    return result;
+  if (!result) {
+    return result.error();
   }
-  result = master->touchBit(localPower);
-  return result;
+  return master->readBit();
 }
 
-error_code DS18B20::copyScratchpad() {
+Result<void> DS18B20::copyScratchpad() {
   const uint_least8_t copyScratchpadCmd = 0x48;
 
   bool hasLocalPower;
-  error_code result = readPowerSupply(hasLocalPower);
-  if (result) {
-    return result;
-  }
-  result = selectRom(*master);
-  if (result) {
+  TRY_VALUE(hasLocalPower, readPowerSupply());
+  Result<void> result = selectRom(*master);
+  if (!result) {
     return result;
   }
   if (hasLocalPower) {
     result = master->writeByte(copyScratchpadCmd);
-    bool recvbit = 0;
-    while (!recvbit && !result) {
-      result = master->touchBit(recvbit);
+    if (result) {
+      bool recvBit;
+      do {
+        TRY_VALUE(recvBit, master->readBit());
+      } while (!recvBit);
     }
   } else {
     result = master->writeByteSetLevel(copyScratchpadCmd,
                                        OneWireMaster::StrongLevel);
-    if (!result) {
+    if (result) {
       sleep->invoke(10);
       result = master->setLevel(OneWireMaster::NormalLevel);
     }
@@ -129,28 +127,27 @@
   return result;
 }
 
-error_code DS18B20::convertTemperature() {
+Result<void> DS18B20::convertTemperature() {
   const uint_least8_t convertTemperatureCmd = 0x44;
 
   bool hasLocalPower;
-  error_code result = readPowerSupply(hasLocalPower);
-  if (result) {
-    return result;
-  }
-  result = selectRom(*master);
-  if (result) {
+  TRY_VALUE(hasLocalPower, readPowerSupply());
+  Result<void> result = selectRom(*master);
+  if (!result) {
     return result;
   }
   if (hasLocalPower) {
     result = master->writeByte(convertTemperatureCmd);
-    bool recvbit = 0;
-    while (!result && !recvbit) {
-      result = master->touchBit(recvbit);
+    if (result) {
+      bool recvBit;
+      do {
+        TRY_VALUE(recvBit, master->readBit());
+      } while (!recvBit);
     }
   } else {
     result = master->writeByteSetLevel(convertTemperatureCmd,
                                        OneWireMaster::StrongLevel);
-    if (!result) {
+    if (result) {
       int sleepTime;
       switch (resolution) {
       case nineBitResolution:
@@ -177,9 +174,9 @@
   return result;
 }
 
-error_code DS18B20::recallEeprom() {
-  error_code result = selectRom(*master);
-  if (!result) {
+Result<void> DS18B20::recallEeprom() {
+  Result<void> result = selectRom(*master);
+  if (result) {
     result = master->writeByte(0xB8);
   }
   return result;
@@ -197,35 +194,28 @@
 
       case DataError:
         return "Data Error";
-
-      default:
-        return defaultErrorMessage(condition);
       }
+      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;
-  }
+Result<int> readTemperature(DS18B20 & ds18b20) {
+  TRY(ds18b20.convertTemperature());
+  DS18B20::Scratchpad scratchpad;
+  TRY_VALUE(scratchpad, ds18b20.readScratchpad());
 
   const unsigned int tempData =
       (static_cast<unsigned int>(scratchpad[1]) << 8) | scratchpad[0];
   const unsigned int signMask = 0xF800;
+  int temperature;
   if ((tempData & signMask) == signMask) {
     temperature = -0x800;
   } else if ((tempData & signMask) == 0) {
     temperature = 0;
   } else {
-    return make_error_code(DS18B20::DataError);
+    return DS18B20::DataError;
   }
   unsigned int precisionMask;
   switch (scratchpad[4]) {
@@ -247,7 +237,7 @@
     break;
   }
   temperature += static_cast<int>(tempData & ~(signMask | precisionMask));
-  return error_code();
+  return temperature;
 }
 
 } // namespace MaximInterfaceDevices
--- a/MaximInterfaceDevices/DS18B20.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS18B20.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,10 +30,10 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceDevices_DS18B20
-#define MaximInterfaceDevices_DS18B20
+#ifndef MaximInterfaceDevices_DS18B20_hpp
+#define MaximInterfaceDevices_DS18B20_hpp
 
-#include <MaximInterfaceCore/array_span.hpp>
+#include <MaximInterfaceCore/array.hpp>
 #include <MaximInterfaceCore/SelectRom.hpp>
 #include <MaximInterfaceCore/Sleep.hpp>
 #include "Config.hpp"
@@ -59,7 +59,7 @@
   static const uint_least8_t twelveBitResolution = 0x7F;
 
   /// Holds the contents of the device scratchpad.
-  typedef Core::array_span<uint_least8_t, 8> Scratchpad;
+  typedef Core::array<uint_least8_t, 8> Scratchpad;
 
   DS18B20(Core::Sleep & sleep, Core::OneWireMaster & master,
           const Core::SelectRom & selectRom)
@@ -74,7 +74,7 @@
   }
 
   /// Initializes the device for first time use.
-  MaximInterfaceDevices_EXPORT Core::error_code initialize();
+  MaximInterfaceDevices_EXPORT Core::Result<void> initialize() const;
 
   /// @brief Write Scratchpad Command
   /// @details If the result of a temperature measurement is higher
@@ -85,37 +85,35 @@
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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);
+  /// @returns scratchpad Contents of scratchpad.
+  MaximInterfaceDevices_EXPORT Core::Result<Scratchpad> readScratchpad() const;
 
   /// @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();
+  MaximInterfaceDevices_EXPORT Core::Result<void> copyScratchpad();
 
   /// @brief Read Power Supply command
   /// @details This command determines if the DS18B20 is parasite
   /// powered or has a local supply
-  /// @param[out] localPower
+  /// @returns
   /// 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);
+  MaximInterfaceDevices_EXPORT Core::Result<bool> readPowerSupply() const;
 
   /// @brief Convert Temperature Command
   /// @details This command begins a temperature conversion.
-  MaximInterfaceDevices_EXPORT Core::error_code convertTemperature();
+  MaximInterfaceDevices_EXPORT Core::Result<void> 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 Core::Result<void> recallEeprom();
 
   MaximInterfaceDevices_EXPORT static const Core::error_category &
   errorCategory();
@@ -124,14 +122,24 @@
   Core::SelectRom selectRom;
   Core::OneWireMaster * master;
   const Core::Sleep * sleep;
-  uint_least8_t resolution;
+  mutable 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);
+/// @returns Temperature in degrees Celsius multiplied by 16.
+MaximInterfaceDevices_EXPORT Core::Result<int>
+readTemperature(DS18B20 & ds18b20);
+
+} // namespace MaximInterfaceDevices
+namespace MaximInterfaceCore {
+
+template <>
+struct is_error_code_enum<MaximInterfaceDevices::DS18B20::ErrorValue>
+    : true_type {};
+
+} // namespace MaximInterfaceCore
+namespace MaximInterfaceDevices {
 
 inline Core::error_code make_error_code(DS18B20::ErrorValue e) {
   return Core::error_code(e, DS18B20::errorCategory());
--- a/MaximInterfaceDevices/DS1920.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS1920.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -38,38 +38,42 @@
 
 using namespace Core;
 
-error_code DS1920::writeScratchpad(uint_least8_t th, uint_least8_t tl) {
-  error_code result = selectRom(*master);
-  if (!result) {
+Result<void> DS1920::writeScratchpad(uint_least8_t th, uint_least8_t tl) {
+  Result<void> 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);
+Result<DS1920::Scratchpad> DS1920::readScratchpad() const {
+  Result<void> result = selectRom(*master);
+  if (!result) {
+    return result.error();
+  }
+  result = master->writeByte(0xBE);
   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();
+  }
+  Scratchpad scratchpad;
+  result = master->readBlock(scratchpad);
+  if (!result) {
+    return result.error();
   }
-  return result;
+  uint_least8_t receivedCrc;
+  MaximInterfaceCore_TRY_VALUE(receivedCrc, master->readByte());
+  if (receivedCrc != calculateCrc8(scratchpad)) {
+    return CrcError;
+  }
+  return scratchpad;
 }
 
-error_code DS1920::copyScratchpad() {
-  error_code result = selectRom(*master);
-  if (!result) {
+Result<void> DS1920::copyScratchpad() {
+  Result<void> result = selectRom(*master);
+  if (result) {
     result = master->writeByteSetLevel(0x48, OneWireMaster::StrongLevel);
-    if (!result) {
+    if (result) {
       sleep->invoke(10);
       result = master->setLevel(OneWireMaster::NormalLevel);
     }
@@ -77,11 +81,11 @@
   return result;
 }
 
-error_code DS1920::convertTemperature() {
-  error_code result = selectRom(*master);
-  if (!result) {
+Result<void> DS1920::convertTemperature() {
+  Result<void> result = selectRom(*master);
+  if (result) {
     result = master->writeByteSetLevel(0x44, OneWireMaster::StrongLevel);
-    if (!result) {
+    if (result) {
       sleep->invoke(750);
       result = master->setLevel(OneWireMaster::NormalLevel);
     }
@@ -89,9 +93,9 @@
   return result;
 }
 
-error_code DS1920::recallEeprom() {
-  error_code result = selectRom(*master);
-  if (!result) {
+Result<void> DS1920::recallEeprom() {
+  Result<void> result = selectRom(*master);
+  if (result) {
     result = master->writeByte(0xB8);
   }
   return result;
@@ -109,39 +113,32 @@
 
       case DataError:
         return "Data Error";
-
-      default:
-        return defaultErrorMessage(condition);
       }
+      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;
-  }
+Result<int> readTemperature(DS1920 & ds1920) {
+  MaximInterfaceCore_TRY(ds1920.convertTemperature());
+  DS1920::Scratchpad scratchpad;
+  MaximInterfaceCore_TRY_VALUE(scratchpad, ds1920.readScratchpad());
 
   unsigned int tempData =
       (static_cast<unsigned int>(scratchpad[1]) << 8) | scratchpad[0];
   const unsigned int signMask = 0xFF00;
+  int temperature;
   if ((tempData & signMask) == signMask) {
     temperature = -0x100;
     tempData &= ~signMask;
   } else if ((tempData & signMask) == 0) {
     temperature = 0;
   } else {
-    return make_error_code(DS1920::DataError);
+    return DS1920::DataError;
   }
   temperature += static_cast<int>(tempData);
-  return error_code();
+  return temperature;
 }
 
 } // namespace MaximInterfaceDevices
--- a/MaximInterfaceDevices/DS1920.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS1920.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,10 +30,10 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceDevices_DS1920
-#define MaximInterfaceDevices_DS1920
+#ifndef MaximInterfaceDevices_DS1920_hpp
+#define MaximInterfaceDevices_DS1920_hpp
 
-#include <MaximInterfaceCore/array_span.hpp>
+#include <MaximInterfaceCore/array.hpp>
 #include <MaximInterfaceCore/SelectRom.hpp>
 #include <MaximInterfaceCore/Sleep.hpp>
 #include "Config.hpp"
@@ -55,7 +55,7 @@
   enum ErrorValue { CrcError = 1, DataError };
 
   /// Holds the contents of the device scratchpad.
-  typedef Core::array_span<uint_least8_t, 8> Scratchpad;
+  typedef Core::array<uint_least8_t, 8> Scratchpad;
 
   DS1920(Core::Sleep & sleep, Core::OneWireMaster & master,
          const Core::SelectRom & selectRom)
@@ -77,28 +77,27 @@
   /// 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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);
+  /// @returns Contents of scratchpad.
+  MaximInterfaceDevices_EXPORT Core::Result<Scratchpad> readScratchpad() const;
 
   /// @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();
+  MaximInterfaceDevices_EXPORT Core::Result<void> copyScratchpad();
 
   /// @brief Convert Temperature Command
   /// @details This command begins a temperature conversion.
-  MaximInterfaceDevices_EXPORT Core::error_code convertTemperature();
+  MaximInterfaceDevices_EXPORT Core::Result<void> 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 Core::Result<void> recallEeprom();
 
   MaximInterfaceDevices_EXPORT static const Core::error_category &
   errorCategory();
@@ -111,9 +110,18 @@
 
 /// @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);
+/// @returns Temperature in degrees Celsius multiplied by 2.
+MaximInterfaceDevices_EXPORT Core::Result<int> readTemperature(DS1920 & ds1920);
+
+} // namespace MaximInterfaceDevices
+namespace MaximInterfaceCore {
+
+template <>
+struct is_error_code_enum<MaximInterfaceDevices::DS1920::ErrorValue>
+    : true_type {};
+
+} // namespace MaximInterfaceCore
+namespace MaximInterfaceDevices {
 
 inline Core::error_code make_error_code(DS1920::ErrorValue e) {
   return Core::error_code(e, DS1920::errorCategory());
--- a/MaximInterfaceDevices/DS2413.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS2413.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -34,20 +34,18 @@
 #include <MaximInterfaceCore/OneWireMaster.hpp>
 #include "DS2413.hpp"
 
+#define TRY MaximInterfaceCore_TRY
+#define TRY_VALUE MaximInterfaceCore_TRY_VALUE
+
 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;
+Result<DS2413::Status> DS2413::readStatus() const {
+  return Result<DS2413::Status>(pioAccessRead());
 }
 
-error_code DS2413::writeOutputState(bool pioAState, bool pioBState) {
+Result<void> DS2413::writeOutputState(bool pioAState, bool pioBState) {
   uint_least8_t val = 0xFC;
   if (pioAState) {
     val |= 0x1;
@@ -58,33 +56,22 @@
   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;
+Result<uint_least8_t> DS2413::pioAccessRead() const {
+  TRY(selectRom(*master));
+  TRY(master->writeByte(0xF5));
+  uint_least8_t result;
+  TRY_VALUE(result, master->readByte());
+  return (result == ((result ^ 0xF0) >> 4)) ? makeResult(result)
+                                            : CommunicationError;
 }
 
-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;
+Result<void> DS2413::pioAccessWrite(uint_least8_t val) {
+  TRY(selectRom(*master));
+  const uint_least8_t block[] = {0x5A, val,
+                                 static_cast<uint_least8_t>(val ^ 0xFF)};
+  TRY(master->writeBlock(block));
+  TRY_VALUE(val, master->readByte());
+  return (val == 0xAA) ? makeResult(none) : CommunicationError;
 }
 
 const error_category & DS2413::errorCategory() {
@@ -103,24 +90,22 @@
   return instance;
 }
 
-error_code writePioAOutputState(DS2413 & ds2413, bool pioAState) {
+Result<void> 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]);
+  TRY_VALUE(status, ds2413.readStatus());
+  if (pioAState != status[DS2413::PioAOutputState]) {
+    TRY(ds2413.writeOutputState(pioAState, status[DS2413::PioBOutputState]));
   }
-  return result;
+  return none;
 }
 
-error_code writePioBOutputState(DS2413 & ds2413, bool pioBState) {
+Result<void> 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);
+  TRY_VALUE(status, ds2413.readStatus());
+  if (pioBState != status[DS2413::PioBOutputState]) {
+    TRY(ds2413.writeOutputState(status[DS2413::PioAOutputState], pioBState));
   }
-  return result;
+  return none;
 }
 
 } // namespace MaximInterfaceDevices
--- a/MaximInterfaceDevices/DS2413.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS2413.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceDevices_DS2413
-#define MaximInterfaceDevices_DS2413
+#ifndef MaximInterfaceDevices_DS2413_hpp
+#define MaximInterfaceDevices_DS2413_hpp
 
 #include <stdint.h>
 #include <MaximInterfaceCore/FlagSet.hpp>
@@ -72,32 +72,41 @@
   }
 
   /// Read the input and output logic states for all PIO pins.
-  MaximInterfaceDevices_EXPORT Core::error_code
-  readStatus(Status & status) const;
+  MaximInterfaceDevices_EXPORT Core::Result<Status> readStatus() const;
 
   /// Write the output logic states for all PIO pins.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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::Result<uint_least8_t> pioAccessRead() const;
+  Core::Result<void> pioAccessWrite(uint_least8_t val);
 
   Core::SelectRom selectRom;
   Core::OneWireMaster * master;
 };
 
 /// Write the output logic state for only PIOA.
-MaximInterfaceDevices_EXPORT Core::error_code
+MaximInterfaceDevices_EXPORT Core::Result<void>
 writePioAOutputState(DS2413 & ds2413, bool pioAState);
 
 /// Write the output logic state for only PIOB.
-MaximInterfaceDevices_EXPORT Core::error_code
+MaximInterfaceDevices_EXPORT Core::Result<void>
 writePioBOutputState(DS2413 & ds2413, bool pioBState);
 
+} // namespace MaximInterfaceDevices
+namespace MaximInterfaceCore {
+
+template <>
+struct is_error_code_enum<MaximInterfaceDevices::DS2413::ErrorValue>
+    : true_type {};
+
+} // namespace MaximInterfaceCore
+namespace MaximInterfaceDevices {
+
 inline Core::error_code make_error_code(DS2413::ErrorValue e) {
   return Core::error_code(e, DS2413::errorCategory());
 }
--- a/MaximInterfaceDevices/DS2431.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS2431.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -39,119 +39,118 @@
 
 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) {
+Result<void> writeMemory(DS2431 & device, uint_least8_t targetAddress,
+                         DS2431::Scratchpad::const_span data) {
+  Result<void> 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;
+  if (const Result<std::pair<uint_least8_t, DS2431::Scratchpad::array> >
+          scratchpad = device.readScratchpad()) {
+    esByte = scratchpad.value().first;
+  } else {
+    return scratchpad.error();
   }
   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) {
+Result<void> DS2431::readMemory(uint_least8_t beginAddress,
+                                span<uint_least8_t> data) const {
+  Result<void> result = selectRom(*master);
+  if (!result) {
     return result;
   }
   const uint_least8_t sendBlock[] = {0xF0, beginAddress, 0x00};
   result = master->writeBlock(sendBlock);
-  if (result) {
+  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) {
+Result<void> DS2431::writeScratchpad(uint_least8_t targetAddress,
+                                     Scratchpad::const_span data) {
+  Result<void> 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) {
+  if (!result) {
     return result;
   }
   const uint_fast16_t calculatedCrc = calculateCrc16(block) ^ 0xFFFFu;
   result = master->readBlock(make_span(block, 2));
-  if (result) {
+  if (!result) {
     return result;
   }
   if (calculatedCrc !=
       ((static_cast<uint_fast16_t>(block[1]) << 8) | block[0])) {
-    result = make_error_code(CrcError);
+    result = CrcError;
   }
   return result;
 }
 
-error_code DS2431::readScratchpad(Scratchpad::span data,
-                                  uint_least8_t & esByte) {
+Result<std::pair<uint_least8_t, DS2431::Scratchpad::array> >
+DS2431::readScratchpad() const {
   typedef array<uint_least8_t, 6 + Scratchpad::size> Block;
 
-  error_code result = selectRom(*master);
-  if (result) {
-    return result;
+  Result<void> result = selectRom(*master);
+  if (!result) {
+    return result.error();
   }
   Block block = {0xAA};
   result = master->writeByte(block.front());
-  if (result) {
-    return result;
+  if (!result) {
+    return result.error();
   }
   result = master->readBlock(make_span(block).subspan(1));
-  if (result) {
-    return result;
+  if (!result) {
+    return result.error();
   }
   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);
+  if (expectedCrc != receivedCrc) {
+    return CrcError;
   }
-  return result;
+  std::pair<uint_least8_t, Scratchpad::array> data;
+  Block::const_iterator blockItEnd = blockIt;
+  blockIt -= data.second.size();
+  std::copy(blockIt, blockItEnd, data.second.begin());
+  data.first = *(--blockIt);
+  return data;
 }
 
-error_code DS2431::copyScratchpad(Address targetAddress, uint_least8_t esByte) {
-  error_code result = selectRom(*master);
-  if (result) {
+Result<void> DS2431::copyScratchpad(uint_least8_t targetAddress,
+                                    uint_least8_t esByte) {
+  Result<void> result = selectRom(*master);
+  if (!result) {
     return result;
   }
   uint_least8_t block[] = {0x55, targetAddress, 0x00};
   result = master->writeBlock(block);
-  if (result) {
+  if (!result) {
     return result;
   }
   result = master->writeByteSetLevel(esByte, OneWireMaster::StrongLevel);
-  if (result) {
+  if (!result) {
     return result;
   }
   sleep->invoke(10);
   result = master->setLevel(OneWireMaster::NormalLevel);
-  if (result) {
+  if (!result) {
     return result;
   }
-  result = master->readByte(block[0]);
-  if (result) {
-    return result;
-  }
+  MaximInterfaceCore_TRY_VALUE(block[0], master->readByte());
   if (block[0] != 0xAA) {
-    result = make_error_code(OperationFailure);
+    result = OperationFailure;
   }
   return result;
 }
--- a/MaximInterfaceDevices/DS2431.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS2431.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,9 +30,10 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceDevices_DS2431
-#define MaximInterfaceDevices_DS2431
+#ifndef MaximInterfaceDevices_DS2431_hpp
+#define MaximInterfaceDevices_DS2431_hpp
 
+#include <utility>
 #include <MaximInterfaceCore/array_span.hpp>
 #include <MaximInterfaceCore/SelectRom.hpp>
 #include <MaximInterfaceCore/Sleep.hpp>
@@ -57,7 +58,6 @@
   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)
@@ -74,29 +74,29 @@
   /// @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;
+  MaximInterfaceDevices_EXPORT Core::Result<void>
+  readMemory(uint_least8_t 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);
+  MaximInterfaceDevices_EXPORT Core::Result<void>
+  writeScratchpad(uint_least8_t 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);
+  /// @returns E/S byte and scratchpad data.
+  MaximInterfaceDevices_EXPORT
+      Core::Result<std::pair<uint_least8_t, Scratchpad::array> >
+      readScratchpad() const;
 
   /// @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 Core::Result<void>
+  copyScratchpad(uint_least8_t targetAddress, uint_least8_t esByte);
 
   MaximInterfaceDevices_EXPORT static const Core::error_category &
   errorCategory();
@@ -113,10 +113,20 @@
 /// @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,
+MaximInterfaceDevices_EXPORT Core::Result<void>
+writeMemory(DS2431 & device, uint_least8_t targetAddress,
             DS2431::Scratchpad::const_span data);
 
+} // namespace MaximInterfaceDevices
+namespace MaximInterfaceCore {
+
+template <>
+struct is_error_code_enum<MaximInterfaceDevices::DS2431::ErrorValue>
+    : true_type {};
+
+} // namespace MaximInterfaceCore
+namespace MaximInterfaceDevices {
+
 inline Core::error_code make_error_code(DS2431::ErrorValue e) {
   return Core::error_code(e, DS2431::errorCategory());
 }
--- a/MaximInterfaceDevices/DS2465.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS2465.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -33,15 +33,20 @@
 #include <MaximInterfaceCore/Error.hpp>
 #include "DS2465.hpp"
 
+#define TRY MaximInterfaceCore_TRY
+#define TRY_VALUE MaximInterfaceCore_TRY_VALUE
+
 namespace MaximInterfaceDevices {
 
 using namespace Core;
 
-/// Delay required after writing an EEPROM segment.
+// Delay required after writing an EEPROM segment.
 static const int eepromSegmentWriteDelayMs = 10;
-/// Delay required after writing an EEPROM page such as the secret memory.
+
+// 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.
+
+// Delay required for a SHA computation to complete.
 static const int shaComputationDelayMs = 2;
 
 static const uint_least8_t scratchpad = 0x00;
@@ -49,36 +54,32 @@
 
 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
-};
+// DS2465 status bits.
+static const uint_least8_t status_1WB = 0x01;
+static const uint_least8_t status_PPD = 0x02;
+static const uint_least8_t status_SD = 0x04;
+static const uint_least8_t status_SBR = 0x20;
+static const uint_least8_t status_TSB = 0x40;
+static const uint_least8_t status_DIR = 0x80;
 
 static const int maxBlockSize = 63;
 
 const int DS2465::memoryPages;
 const int DS2465::segmentsPerPage;
 
-error_code DS2465::initialize(Config config) {
+Result<void> DS2465::initialize(Config config) {
   // reset DS2465
-  error_code result = resetDevice();
-  if (!result) {
+  Result<void> 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);
+Result<void> DS2465::computeNextMasterSecret(bool swap, int pageNum,
+                                             PageRegion region) {
+  Result<void> result = ArgumentOutOfRangeError;
   if (pageNum >= 0) {
     const uint_least8_t command[] = {
         0x1E, static_cast<uint_least8_t>(swap ? (0xC8 | (pageNum << 4) | region)
@@ -88,52 +89,52 @@
   return result;
 }
 
-error_code DS2465::computeWriteMac(bool regwrite, bool swap, int pageNum,
-                                   int segmentNum) const {
-  error_code result = make_error_code(ArgumentOutOfRangeError);
+Result<void> DS2465::computeWriteMac(bool regwrite, bool swap, int pageNum,
+                                     int segmentNum) const {
+  Result<void> result = 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) {
+    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);
+Result<void> DS2465::computeAuthMac(bool swap, int pageNum,
+                                    PageRegion region) const {
+  Result<void> result = 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) {
+    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);
+Result<void> DS2465::computeSlaveSecret(bool swap, int pageNum,
+                                        PageRegion region) {
+  Result<void> result = 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) {
+    if (result) {
       sleep->invoke(shaComputationDelayMs * 2);
     }
   }
   return result;
 }
 
-error_code DS2465::readPage(int pageNum, Page::span data) const {
+Result<DS2465::Page::array> DS2465::readPage(int pageNum) const {
   uint_least8_t addr;
   switch (pageNum) {
   case 0:
@@ -143,48 +144,50 @@
     addr = 0xA0;
     break;
   default:
-    return make_error_code(ArgumentOutOfRangeError);
+    return ArgumentOutOfRangeError;
   }
-  return readMemory(addr, data);
+  Page::array data;
+  TRY(readMemory(addr, data));
+  return data;
 }
 
-error_code DS2465::writePage(int pageNum, Page::const_span data) {
-  error_code result = writeMemory(scratchpad, data);
-  if (!result) {
+Result<void> DS2465::writePage(int pageNum, Page::const_span data) {
+  Result<void> result = writeMemory(scratchpad, data);
+  if (result) {
     result = copyScratchpad(false, pageNum, false, 0);
   }
-  if (!result) {
+  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<void> DS2465::writeSegment(int pageNum, int segmentNum,
+                                  Segment::const_span data) {
+  Result<void> result = writeMemory(scratchpad, data);
+  if (result) {
     result = copyScratchpad(false, pageNum, true, segmentNum);
   }
-  if (!result) {
+  if (result) {
     sleep->invoke(eepromSegmentWriteDelayMs);
   }
   return result;
 }
 
-error_code DS2465::writeMasterSecret(Page::const_span masterSecret) {
-  error_code result = writeMemory(scratchpad, masterSecret);
-  if (!result) {
+Result<void> DS2465::writeMasterSecret(Page::const_span masterSecret) {
+  Result<void> result = writeMemory(scratchpad, masterSecret);
+  if (result) {
     result = copyScratchpad(true, 0, false, 0);
   }
-  if (!result) {
+  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);
+Result<void> DS2465::copyScratchpad(bool destSecret, int pageNum, bool notFull,
+                                    int segmentNum) {
+  Result<void> result = ArgumentOutOfRangeError;
   if (pageNum >= 0 && segmentNum >= 0) {
     const uint_least8_t command[] = {
         0x5A,
@@ -196,41 +199,41 @@
   return result;
 }
 
-error_code DS2465::configureLevel(Level level) {
+Result<void> DS2465::configureLevel(Level level) {
   // Check if supported level
   if (!((level == NormalLevel) || (level == StrongLevel))) {
-    return make_error_code(InvalidLevelError);
+    return InvalidLevelError;
   }
   // Check if requested level already set
   if (curConfig.getSPU() == (level == StrongLevel)) {
-    return error_code();
+    return none;
   }
   // Set the level
   return writeConfig(Config(curConfig).setSPU(level == StrongLevel));
 }
 
-error_code DS2465::setLevel(Level newLevel) {
+Result<void> DS2465::setLevel(Level newLevel) {
   if (newLevel == StrongLevel) {
-    return make_error_code(InvalidLevelError);
+    return InvalidLevelError;
   }
 
   return configureLevel(newLevel);
 }
 
-error_code DS2465::setSpeed(Speed newSpeed) {
+Result<void> DS2465::setSpeed(Speed newSpeed) {
   // Check if supported speed
   if (!((newSpeed == OverdriveSpeed) || (newSpeed == StandardSpeed))) {
-    return make_error_code(InvalidSpeedError);
+    return InvalidSpeedError;
   }
   // Check if requested speed is already set
   if (curConfig.get1WS() == (newSpeed == OverdriveSpeed)) {
-    return error_code();
+    return none;
   }
   // Set the speed
   return writeConfig(Config(curConfig).set1WS(newSpeed == OverdriveSpeed));
 }
 
-error_code DS2465::triplet(TripletData & data) {
+Result<OneWireMaster::TripletData> DS2465::triplet(bool sendBit) {
   // 1-Wire Triplet (Case B)
   //   S AD,0 [A] 1WT [A] SS [A] Sr AD,1 [A] [Status] A [Status] A\ P
   //                                         \--------/
@@ -239,89 +242,74 @@
   //  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;
+      0x78, static_cast<uint_least8_t>(sendBit ? 0x80 : 0x00)};
+  TRY(writeMemory(commandReg, command));
+
+  uint_least8_t status;
+  TRY_VALUE(status, pollBusy());
+
+  TripletData data;
+  data.readBit = ((status & status_SBR) == status_SBR);
+  data.readBitComplement = ((status & status_TSB) == status_TSB);
+  data.writeBit = ((status & status_DIR) == status_DIR);
+  return data;
 }
 
-error_code DS2465::readBlock(span<uint_least8_t> recvBuf) {
+Result<void> 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) {
+  while (recvIdx < recvBuf.size()) {
     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]));
-    }
+    TRY(writeMemory(commandReg, command));
+    TRY(pollBusy());
+    TRY(readMemory(scratchpad, recvBuf.subspan(recvIdx, command[1])));
     recvIdx += command[1];
   }
-  return result;
+  return none;
 }
 
-error_code DS2465::writeBlock(span<const uint_least8_t> sendBuf) {
-  error_code result;
+Result<void> DS2465::writeBlock(span<const uint_least8_t> sendBuf) {
   span<const uint_least8_t>::index_type sendIdx = 0;
-  while (sendIdx < sendBuf.size() && !result) {
+  while (sendIdx < sendBuf.size()) {
     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]));
+    TRY(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();
-    }
+    TRY(writeMemory(commandReg, command));
+    TRY(pollBusy());
     sendIdx += command[1];
   }
-  return result;
+  return none;
 }
 
-error_code DS2465::writeMacBlock() const {
+Result<void> DS2465::writeMacBlock() {
   // 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;
+  TRY(writeMemory(commandReg, command));
+  TRY(pollBusy());
+  return none;
 }
 
-error_code DS2465::readByteSetLevel(uint_least8_t & recvByte,
-                                    Level afterLevel) {
+Result<uint_least8_t> DS2465::readByteSetLevel(Level afterLevel) {
   // 1-Wire Read Bytes (Case C)
   //   S AD,0 [A] CommandReg [A] 1WRB [A] Sr AD,1 [A] [Status] A [Status] A
   //                                                  \--------/
@@ -331,27 +319,17 @@
   //  [] indicates from slave
   //  DD data read
 
-  error_code result = configureLevel(afterLevel);
-  if (result) {
-    return result;
-  }
+  TRY(configureLevel(afterLevel));
 
-  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;
+  uint_least8_t buf = 0x96;
+  TRY(writeMemory(commandReg, make_span(&buf, 1)));
+  TRY(pollBusy());
+  TRY(readMemory(0x62, make_span(&buf, 1)));
+  return buf;
 }
 
-error_code DS2465::writeByteSetLevel(uint_least8_t sendByte, Level afterLevel) {
+Result<void> 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
@@ -360,22 +338,15 @@
   //  [] indicates from slave
   //  DD data to write
 
-  error_code result = configureLevel(afterLevel);
-  if (result) {
-    return result;
-  }
+  TRY(configureLevel(afterLevel));
 
   const uint_least8_t command[] = {0xA5, sendByte};
-  result = writeMemory(commandReg, command);
-  if (result) {
-    return result;
-  }
-
-  result = pollBusy();
-  return result;
+  TRY(writeMemory(commandReg, command));
+  TRY(pollBusy());
+  return none;
 }
 
-error_code DS2465::touchBitSetLevel(bool & sendRecvBit, Level afterLevel) {
+Result<bool> DS2465::touchBitSetLevel(bool sendBit, 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
@@ -384,28 +355,20 @@
   //  [] indicates from slave
   //  BB indicates byte containing bit value in msbit
 
-  error_code result = configureLevel(afterLevel);
-  if (result) {
-    return result;
-  }
+  TRY(configureLevel(afterLevel));
 
   const uint_least8_t command[] = {
-      0x87, static_cast<uint_least8_t>(sendRecvBit ? 0x80 : 0x00)};
-  result = writeMemory(commandReg, command);
-  if (result) {
-    return result;
-  }
+      0x87, static_cast<uint_least8_t>(sendBit ? 0x80 : 0x00)};
+  TRY(writeMemory(commandReg, command));
 
   uint_least8_t status;
-  result = pollBusy(&status);
-  if (!result) {
-    sendRecvBit = ((status & Status_SBR) == Status_SBR);
-  }
-  return result;
+  TRY_VALUE(status, pollBusy());
+
+  return (status & status_SBR) == status_SBR;
 }
 
-error_code DS2465::writeMemory(uint_least8_t addr,
-                               span<const uint_least8_t> buf) const {
+Result<void> 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
   //                      \-----/
@@ -414,18 +377,18 @@
   //  VSA valid SRAM memory address
   //  DD memory data to write
 
-  error_code result = master->start(address_);
-  if (result) {
+  Result<void> result = master->start(address_);
+  if (!result) {
     master->stop();
     return result;
   }
   result = master->writeByte(addr);
-  if (result) {
+  if (!result) {
     master->stop();
     return result;
   }
   result = master->writeBlock(buf);
-  if (result) {
+  if (!result) {
     master->stop();
     return result;
   }
@@ -433,8 +396,8 @@
   return result;
 }
 
-error_code DS2465::readMemory(uint_least8_t addr,
-                              span<uint_least8_t> buf) const {
+Result<void> 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
   //                                 \-----/
@@ -443,13 +406,13 @@
   //  MA memory address
   //  DD memory data read
 
-  error_code result = master->start(address_);
-  if (result) {
+  Result<void> result = master->start(address_);
+  if (!result) {
     master->stop();
     return result;
   }
   result = master->writeByte(addr);
-  if (result) {
+  if (!result) {
     master->stop();
     return result;
   }
@@ -457,14 +420,14 @@
   return result;
 }
 
-error_code DS2465::readMemory(span<uint_least8_t> buf) const {
-  error_code result = master->start(address_ | 1);
-  if (result) {
+Result<void> DS2465::readMemory(span<uint_least8_t> buf) const {
+  Result<void> result = master->start(address_ | 1);
+  if (!result) {
     master->stop();
     return result;
   }
-  result = master->readBlock(I2CMaster::Nack, buf);
-  if (result) {
+  result = master->readBlock(buf, I2CMaster::Nack);
+  if (!result) {
     master->stop();
     return result;
   }
@@ -472,27 +435,26 @@
   return result;
 }
 
-error_code DS2465::writeConfig(Config config) {
+Result<void> 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<void> 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 && configBuf != config.readByte()) {
+    result = HardwareError;
   }
-  if (!result) {
+  if (result) {
     curConfig = config;
   }
   return result;
 }
 
-error_code DS2465::writePortParameter(PortParameter param, int val) {
+Result<void> DS2465::writePortParameter(PortParameter param, int val) {
   if (val < 0 || val > 15) {
-    return make_error_code(ArgumentOutOfRangeError);
+    return ArgumentOutOfRangeError;
   }
 
   uint_least8_t addr = 0;
@@ -521,8 +483,8 @@
   }
 
   uint_least8_t data;
-  error_code result = readMemory(addr, make_span(&data, 1));
-  if (result) {
+  Result<void> result = readMemory(addr, make_span(&data, 1));
+  if (!result) {
     return result;
   }
 
@@ -539,28 +501,24 @@
   return result;
 }
 
-error_code DS2465::pollBusy(uint_least8_t * pStatus) const {
+Result<uint_least8_t> DS2465::pollBusy() 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;
+    const Result<void> result = readMemory(make_span(&status, 1));
+    if (!result) {
+      return result.error();
     }
     if (pollCount++ >= pollLimit) {
-      return make_error_code(HardwareError);
+      return HardwareError;
     }
-  } while (status & Status_1WB);
-
-  return error_code();
+  } while ((status & status_1WB) == status_1WB);
+  return status;
 }
 
-error_code DS2465::reset() {
+Result<void> DS2465::reset() {
   // 1-Wire reset (Case B)
   //   S AD,0 [A] CommandReg  [A] 1WRS [A] Sr AD,1 [A] [Status] A [Status] A\ P
   //                                                  \--------/
@@ -568,191 +526,210 @@
   //  [] indicates from slave
 
   uint_least8_t buf = 0xB4;
-  error_code result = writeMemory(commandReg, make_span(&buf, 1));
+  TRY(writeMemory(commandReg, make_span(&buf, 1)));
+
+  TRY_VALUE(buf, pollBusy());
 
-  if (!result) {
-    result = pollBusy(&buf);
+  if ((buf & status_SD) == status_SD) {
+    return ShortDetectedError;
+  }
+  if ((buf & status_PPD) != status_PPD) {
+    return NoSlaveError;
   }
 
-  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;
+  return none;
 }
 
-error_code DS2465::resetDevice() {
+Result<void> 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));
+  Result<void> result = writeMemory(commandReg, make_span(&buf, 1));
 
-  if (!result) {
+  if (result) {
     result = readMemory(make_span(&buf, 1));
   }
 
-  if (!result) {
+  if (result) {
     if ((buf & 0xF7) != 0x10) {
-      result = make_error_code(HardwareError);
+      result = HardwareError;
     }
   }
 
-  if (!result) {
+  if (result) {
     reset(); // do a command to get 1-Wire master reset out of holding state
   }
 
   return result;
 }
 
-error_code
+Result<void>
 DS2465::computeNextMasterSecret(AuthenticationData::const_span data) {
-  error_code result = writeMemory(scratchpad, data);
-  if (!result) {
+  Result<void> result = writeMemory(scratchpad, data);
+  if (result) {
     result = computeNextMasterSecret(false, 0, FullPage);
   }
   return result;
 }
 
-error_code
+Result<void>
 DS2465::computeNextMasterSecretWithSwap(AuthenticationData::const_span data,
                                         int pageNum, PageRegion region) {
-  error_code result = writeMemory(scratchpad, data);
-  if (!result) {
+  Result<void> 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<void> DS2465::doComputeWriteMac(WriteMacData::const_span data) const {
+  Result<void> 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);
+Result<DS2465::Page::array>
+DS2465::computeWriteMac(WriteMacData::const_span data) const {
+  Result<void> result = doComputeWriteMac(data);
   if (!result) {
-    result = readMemory(mac);
+    return result.error();
   }
-  return result;
+  Page::array mac;
+  result = readMemory(mac);
+  if (!result) {
+    return result.error();
+  }
+  return mac;
 }
 
-error_code
-DS2465::computeAndTransmitWriteMac(WriteMacData::const_span data) const {
-  error_code result = computeWriteMac(data);
-  if (!result) {
+Result<void> DS2465::computeAndTransmitWriteMac(WriteMacData::const_span data) {
+  Result<void> result = doComputeWriteMac(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<void> DS2465::doComputeWriteMacWithSwap(WriteMacData::const_span data,
+                                               int pageNum,
+                                               int segmentNum) const {
+  Result<void> 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);
+Result<DS2465::Page::array>
+DS2465::computeWriteMacWithSwap(WriteMacData::const_span data, int pageNum,
+                                int segmentNum) const {
+  Result<void> result = doComputeWriteMacWithSwap(data, pageNum, segmentNum);
   if (!result) {
-    result = readMemory(mac);
+    return result.error();
   }
-  return result;
+  Page::array mac;
+  result = readMemory(mac);
+  if (!result) {
+    return result.error();
+  }
+  return mac;
 }
 
-error_code
+Result<void>
 DS2465::computeAndTransmitWriteMacWithSwap(WriteMacData::const_span data,
-                                           int pageNum, int segmentNum) const {
-  error_code result = computeWriteMacWithSwap(data, pageNum, segmentNum);
-  if (!result) {
+                                           int pageNum, int segmentNum) {
+  Result<void> result = doComputeWriteMacWithSwap(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<void> DS2465::computeSlaveSecret(AuthenticationData::const_span data) {
+  Result<void> result = writeMemory(scratchpad, data);
+  if (result) {
     result = computeSlaveSecret(false, 0, FullPage);
   }
   return result;
 }
 
-error_code
+Result<void>
 DS2465::computeSlaveSecretWithSwap(AuthenticationData::const_span data,
                                    int pageNum, PageRegion region) {
-  error_code result = writeMemory(scratchpad, data);
-  if (!result) {
+  Result<void> 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<void>
+DS2465::doComputeAuthMac(AuthenticationData::const_span data) const {
+  Result<void> 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);
+Result<DS2465::Page::array>
+DS2465::computeAuthMac(AuthenticationData::const_span data) const {
+  Result<void> result = doComputeAuthMac(data);
   if (!result) {
-    result = readMemory(mac);
+    return result.error();
   }
-  return result;
+  Page::array mac;
+  result = readMemory(mac);
+  if (!result) {
+    return result.error();
+  }
+  return mac;
 }
 
-error_code
-DS2465::computeAndTransmitAuthMac(AuthenticationData::const_span data) const {
-  error_code result = computeAuthMac(data);
-  if (!result) {
+Result<void>
+DS2465::computeAndTransmitAuthMac(AuthenticationData::const_span data) {
+  Result<void> result = doComputeAuthMac(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<void>
+DS2465::doComputeAuthMacWithSwap(AuthenticationData::const_span data,
+                                 int pageNum, PageRegion region) const {
+  Result<void> 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);
+Result<DS2465::Page::array>
+DS2465::computeAuthMacWithSwap(AuthenticationData::const_span data, int pageNum,
+                               PageRegion region) const {
+  Result<void> result = doComputeAuthMacWithSwap(data, pageNum, region);
   if (!result) {
-    result = readMemory(mac);
+    return result.error();
   }
-  return result;
+  Page::array mac;
+  result = readMemory(mac);
+  if (!result) {
+    return result.error();
+  }
+  return mac;
 }
 
-error_code DS2465::computeAndTransmitAuthMacWithSwap(
-    AuthenticationData::const_span data, int pageNum, PageRegion region) const {
-  error_code result = computeAuthMacWithSwap(data, pageNum, region);
-  if (!result) {
+Result<void>
+DS2465::computeAndTransmitAuthMacWithSwap(AuthenticationData::const_span data,
+                                          int pageNum, PageRegion region) {
+  Result<void> result = doComputeAuthMacWithSwap(data, pageNum, region);
+  if (result) {
     result = writeMacBlock();
   }
   return result;
@@ -770,10 +747,8 @@
 
       case ArgumentOutOfRangeError:
         return "Argument Out of Range Error";
-
-      default:
-        return defaultErrorMessage(condition);
       }
+      return defaultErrorMessage(condition);
     }
   } instance;
   return instance;
--- a/MaximInterfaceDevices/DS2465.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS2465.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceDevices_DS2465
-#define MaximInterfaceDevices_DS2465
+#ifndef MaximInterfaceDevices_DS2465_hpp
+#define MaximInterfaceDevices_DS2465_hpp
 
 #include <MaximInterfaceCore/array_span.hpp>
 #include <MaximInterfaceCore/I2CMaster.hpp>
@@ -41,7 +41,11 @@
 
 namespace MaximInterfaceDevices {
 
-/// Interface to the DS2465 1-Wire master and SHA-256 coprocessor.
+/// @brief Interface to the DS2465 1-Wire master and SHA-256 coprocessor.
+/// @details
+/// 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.
 class DS2465 : public Core::OneWireMaster {
 public:
   enum ErrorValue { HardwareError = 1, ArgumentOutOfRangeError };
@@ -173,10 +177,6 @@
     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) {}
@@ -190,158 +190,158 @@
   void setAddress(uint_least8_t address) { address_ = address & 0xFE; }
 
   /// Initialize hardware for use.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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);
+  MaximInterfaceDevices_EXPORT Core::Result<void> 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   writePortParameter(PortParameter param, int val);
 
   // 1-Wire Master Commands
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code reset();
+  MaximInterfaceDevices_EXPORT virtual Core::Result<void> reset();
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
-  touchBitSetLevel(bool & sendRecvBit, Level afterLevel);
+  MaximInterfaceDevices_EXPORT virtual Core::Result<bool>
+  touchBitSetLevel(bool sendBit, Level afterLevel);
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
-  readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+  MaximInterfaceDevices_EXPORT virtual Core::Result<uint_least8_t>
+  readByteSetLevel(Level afterLevel);
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  MaximInterfaceDevices_EXPORT virtual Core::Result<void>
   writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  MaximInterfaceDevices_EXPORT virtual Core::Result<void>
   readBlock(Core::span<uint_least8_t> recvBuf);
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  MaximInterfaceDevices_EXPORT virtual Core::Result<void>
   writeBlock(Core::span<const uint_least8_t> sendBuf);
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  MaximInterfaceDevices_EXPORT virtual Core::Result<void>
   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
+  MaximInterfaceDevices_EXPORT virtual Core::Result<void>
   setLevel(Level newLevel);
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
-  triplet(TripletData & data);
+  MaximInterfaceDevices_EXPORT virtual Core::Result<TripletData>
+  triplet(bool sendBit);
 
   // 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;
+  /// @returns Data that was read.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array>
+  readPage(int pageNum) 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   writeSegment(int pageNum, int segmentNum, Segment::const_span data);
 
   /// Write data to the secret EEPROM memory page.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   writeMasterSecret(Page::const_span masterSecret);
 
   /// @brief Compute Next Master Secret.
   /// @param data Combined data fields for computation.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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;
+  /// @returns Computed Write MAC.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array>
+  computeWriteMac(WriteMacData::const_span data) const;
 
   /// @brief Compute Write MAC.
   /// @param data Combined data fields for computation.
-  MaximInterfaceDevices_EXPORT Core::error_code
-  computeAndTransmitWriteMac(WriteMacData::const_span data) const;
+  MaximInterfaceDevices_EXPORT Core::Result<void>
+  computeAndTransmitWriteMac(WriteMacData::const_span data);
 
   /// @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
+  /// @returns Computed Write MAC.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array>
   computeWriteMacWithSwap(WriteMacData::const_span data, int pageNum,
-                          int segmentNum, Page::span mac) const;
+                          int segmentNum) 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   computeAndTransmitWriteMacWithSwap(WriteMacData::const_span data, int pageNum,
-                                     int segmentNum) const;
+                                     int segmentNum);
 
   /// @brief Compute Slave Secret (S-Secret).
   /// @param data Combined data fields for computation.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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;
+  /// @returns Computed Auth MAC.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array>
+  computeAuthMac(AuthenticationData::const_span data) const;
 
   /// @brief Compute Authentication MAC.
   /// @param data Combined data fields for computation.
-  MaximInterfaceDevices_EXPORT Core::error_code
-  computeAndTransmitAuthMac(AuthenticationData::const_span data) const;
+  MaximInterfaceDevices_EXPORT Core::Result<void>
+  computeAndTransmitAuthMac(AuthenticationData::const_span data);
 
   /// @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
+  /// @returns Computed Auth MAC.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array>
   computeAuthMacWithSwap(AuthenticationData::const_span data, int pageNum,
-                         PageRegion region, Page::span mac) const;
+                         PageRegion region) 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   computeAndTransmitAuthMacWithSwap(AuthenticationData::const_span data,
-                                    int pageNum, PageRegion region) const;
+                                    int pageNum, PageRegion region);
 
   MaximInterfaceDevices_EXPORT static const Core::error_category &
   errorCategory();
@@ -354,62 +354,73 @@
 
   /// @brief Performs a soft reset on the DS2465.
   /// @note This is not a 1-Wire Reset.
-  Core::error_code resetDevice();
+  Core::Result<void> 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;
+  /// Polls the DS2465 status waiting for the 1-Wire Busy bit (1WB) to be cleared.
+  /// @returns Status byte or TimeoutError if poll limit reached.
+  Core::Result<uint_least8_t> pollBusy() 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);
+  Core::Result<void> 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;
+  Core::Result<void> 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;
+  Core::Result<void> 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;
+  Core::Result<void> readMemory(Core::span<uint_least8_t> buf) const;
 
   /// Write the last computed MAC to the 1-Wire bus.
-  Core::error_code writeMacBlock() const;
+  Core::Result<void> writeMacBlock();
 
-  Core::error_code computeWriteMac(WriteMacData::const_span data) const;
+  Core::Result<void> doComputeWriteMac(WriteMacData::const_span data) const;
 
-  Core::error_code computeWriteMacWithSwap(WriteMacData::const_span data,
-                                           int pageNum, int segmentNum) const;
+  Core::Result<void> doComputeWriteMacWithSwap(WriteMacData::const_span data,
+                                               int pageNum,
+                                               int segmentNum) const;
 
-  Core::error_code computeAuthMac(AuthenticationData::const_span data) const;
+  Core::Result<void>
+  doComputeAuthMac(AuthenticationData::const_span data) const;
 
-  Core::error_code computeAuthMacWithSwap(AuthenticationData::const_span data,
-                                          int pageNum, PageRegion region) const;
+  Core::Result<void>
+  doComputeAuthMacWithSwap(AuthenticationData::const_span data, int pageNum,
+                           PageRegion region) const;
 
   // Legacy implementations
-  Core::error_code copyScratchpad(bool destSecret, int pageNum, bool notFull,
-                                  int segmentNum);
+  Core::Result<void> copyScratchpad(bool destSecret, int pageNum, bool notFull,
+                                    int segmentNum);
+
+  Core::Result<void> computeNextMasterSecret(bool swap, int pageNum,
+                                             PageRegion region);
 
-  Core::error_code computeNextMasterSecret(bool swap, int pageNum,
-                                           PageRegion region);
+  Core::Result<void> computeWriteMac(bool regwrite, bool swap, int pageNum,
+                                     int segmentNum) const;
+
+  Core::Result<void> computeSlaveSecret(bool swap, int pageNum,
+                                        PageRegion region);
 
-  Core::error_code computeWriteMac(bool regwrite, bool swap, int pageNum,
-                                   int segmentNum) const;
+  Core::Result<void> computeAuthMac(bool swap, int pageNum,
+                                    PageRegion region) const;
+};
+
+} // namespace MaximInterfaceDevices
+namespace MaximInterfaceCore {
 
-  Core::error_code computeSlaveSecret(bool swap, int pageNum,
-                                      PageRegion region);
+template <>
+struct is_error_code_enum<MaximInterfaceDevices::DS2465::ErrorValue>
+    : true_type {};
 
-  Core::error_code computeAuthMac(bool swap, int pageNum,
-                                  PageRegion region) const;
-};
+} // namespace MaximInterfaceCore
+namespace MaximInterfaceDevices {
 
 inline Core::error_code make_error_code(DS2465::ErrorValue e) {
   return Core::error_code(e, DS2465::errorCategory());
--- a/MaximInterfaceDevices/DS2480B.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS2480B.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -33,6 +33,9 @@
 #include <MaximInterfaceCore/Error.hpp>
 #include "DS2480B.hpp"
 
+#define TRY MaximInterfaceCore_TRY
+#define TRY_VALUE MaximInterfaceCore_TRY_VALUE
+
 // Mode Commands
 #define MODE_DATA 0xE1
 #define MODE_COMMAND 0xE3
@@ -173,23 +176,23 @@
 
 using namespace Core;
 
-error_code DS2480B::initialize() {
+Result<void> 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) {
+  Result<void> result = uart->setBaudRate(4800);
+  if (!result) {
     return result;
   }
   result = uart->sendBreak();
-  if (result) {
+  if (!result) {
     return result;
   }
   result = uart->setBaudRate(9600);
-  if (result) {
+  if (!result) {
     return result;
   }
 
@@ -198,62 +201,55 @@
 
   // Flush the read buffer.
   result = uart->clearReadBuffer();
-  if (result) {
+  if (!result) {
     return result;
   }
 
   // Send the timing byte.
   result = uart->writeByte(CMD_COMM | FUNCTSEL_RESET | SPEEDSEL_STD);
-  if (result) {
+  if (!result) {
     return result;
   }
 
   // Change the DS2480 baud rate.
   result = uart->writeByte(CMD_CONFIG | PARMSEL_BAUDRATE | PARMSET_115200);
-  if (result) {
+  if (!result) {
     return result;
   }
 
   // Change our baud rate.
   result = uart->setBaudRate(115200);
-  if (result) {
+  if (!result) {
     return result;
   }
 
+  // Verify response.
   uint_least8_t response;
-
-  // Verify response.
-  result = uart->readByte(response);
-  if (result) {
-    return result;
-  }
+  TRY_VALUE(response, uart->readByte());
   if ((response & (PARMSEL_MASK | PARMSET_MASK)) !=
       (PARMSEL_BAUDRATE | PARMSET_115200)) {
-    return make_error_code(HardwareError);
+    return HardwareError;
   }
 
   // Set the SPUD time value.
   result = uart->writeByte(CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite);
-  if (result) {
+  if (!result) {
     return result;
   }
 
   // Verify response.
-  result = uart->readByte(response);
-  if (result) {
-    return result;
-  }
+  TRY_VALUE(response, uart->readByte());
   if ((response & (PARMSEL_MASK | PARMSET_MASK)) !=
       (PARMSEL_5VPULSE | PARMSET_infinite)) {
-    return make_error_code(HardwareError);
+    return HardwareError;
   }
 
   return result;
 }
 
-error_code DS2480B::reset() {
+Result<void> DS2480B::reset() {
   if (level != NormalLevel) {
-    return make_error_code(InvalidLevelError);
+    return InvalidLevelError;
   }
 
   uint_least8_t packet[2];
@@ -269,29 +265,25 @@
   packet[packetLen++] = CMD_COMM | FUNCTSEL_RESET | speed;
 
   // Send the packet.
-  error_code result = uart->writeBlock(make_span(packet, packetLen));
-  if (result) {
-    return result;
-  }
+  TRY(uart->writeBlock(make_span(packet, packetLen)));
 
   // Read back the response.
-  result = uart->readByte(packet[0]);
-  if (result) {
-    return result;
-  }
+  TRY_VALUE(packet[0], uart->readByte());
 
   // 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 ShortDetectedError;
   }
-  return result;
+  if ((packet[0] & RB_RESET_MASK) == RB_NOPRESENCE) {
+    return NoSlaveError;
+  }
+
+  return none;
 }
 
-error_code DS2480B::touchBitSetLevel(bool & sendRecvBit, Level afterLevel) {
+Result<bool> DS2480B::touchBitSetLevel(bool sendBit, Level afterLevel) {
   if (level != NormalLevel) {
-    return make_error_code(InvalidLevelError);
+    return InvalidLevelError;
   }
 
   uint_least8_t packet[3];
@@ -304,8 +296,8 @@
   }
 
   // Construct the command.
-  packet[packetLen++] = CMD_COMM | FUNCTSEL_BIT |
-                        (sendRecvBit ? BITPOL_ONE : BITPOL_ZERO) | speed;
+  packet[packetLen++] =
+      CMD_COMM | FUNCTSEL_BIT | (sendBit ? BITPOL_ONE : BITPOL_ZERO) | speed;
   switch (afterLevel) {
   case NormalLevel:
     break;
@@ -317,35 +309,27 @@
     break;
 
   default:
-    return make_error_code(InvalidLevelError);
+    return InvalidLevelError;
   }
 
   // Send the packet.
-  error_code result = uart->writeBlock(make_span(packet, packetLen));
-  if (result) {
-    return result;
-  }
+  TRY(uart->writeBlock(make_span(packet, packetLen)));
 
   // Read back the response.
-  result = uart->readByte(packet[0]);
-  if (result) {
-    return result;
-  }
+  TRY_VALUE(packet[0], uart->readByte());
 
   // 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);
+  if ((packet[0] & 0xE0) != 0x80) {
+    return HardwareError;
   }
-  return result;
+  level = afterLevel;
+  return (packet[0] & RB_BIT_MASK) == RB_BIT_ONE;
 }
 
-error_code DS2480B::writeByteSetLevel(uint_least8_t sendByte,
-                                      Level afterLevel) {
+Result<void> DS2480B::writeByteSetLevel(uint_least8_t sendByte,
+                                        Level afterLevel) {
   if (level != NormalLevel) {
-    return make_error_code(InvalidLevelError);
+    return InvalidLevelError;
   }
 
   switch (afterLevel) {
@@ -356,7 +340,7 @@
     return OneWireMaster::writeByteSetLevel(sendByte, afterLevel);
 
   default:
-    return make_error_code(InvalidLevelError);
+    return InvalidLevelError;
   }
 
   uint_least8_t packet[3];
@@ -377,28 +361,22 @@
   }
 
   // Send the packet.
-  error_code result = uart->writeBlock(make_span(packet, packetLen));
-  if (result) {
-    return result;
-  }
+  TRY(uart->writeBlock(make_span(packet, packetLen)));
 
   // Read back the response.
-  result = uart->readByte(packet[0]);
-  if (result) {
-    return result;
-  }
+  TRY_VALUE(packet[0], uart->readByte());
 
   // Interpret the response.
   if (packet[0] != sendByte) {
-    result = make_error_code(HardwareError);
+    return HardwareError;
   }
-  return result;
+
+  return none;
 }
 
-error_code DS2480B::readByteSetLevel(uint_least8_t & recvByte,
-                                     Level afterLevel) {
+Result<uint_least8_t> DS2480B::readByteSetLevel(Level afterLevel) {
   if (level != NormalLevel) {
-    return make_error_code(InvalidLevelError);
+    return InvalidLevelError;
   }
 
   switch (afterLevel) {
@@ -406,10 +384,10 @@
     break;
 
   case StrongLevel:
-    return OneWireMaster::readByteSetLevel(recvByte, afterLevel);
+    return OneWireMaster::readByteSetLevel(afterLevel);
 
   default:
-    return make_error_code(InvalidLevelError);
+    return InvalidLevelError;
   }
 
   uint_least8_t packet[2];
@@ -425,17 +403,16 @@
   packet[packetLen++] = 0xFF;
 
   // Send the packet.
-  error_code result = uart->writeBlock(make_span(packet, packetLen));
-  if (result) {
-    return result;
+  const Result<void> result = uart->writeBlock(make_span(packet, packetLen));
+  if (!result) {
+    return result.error();
   }
 
   // Read back the response.
-  result = uart->readByte(recvByte);
-  return result;
+  return uart->readByte();
 }
 
-error_code DS2480B::setSpeed(Speed newSpeed) {
+Result<void> DS2480B::setSpeed(Speed newSpeed) {
   uint_least8_t newSpeedByte;
   switch (newSpeed) {
   case OverdriveSpeed:
@@ -447,10 +424,10 @@
     break;
 
   default:
-    return make_error_code(InvalidSpeedError);
+    return InvalidSpeedError;
   }
   if (speed == newSpeedByte) {
-    return error_code();
+    return none;
   }
   speed = newSpeedByte;
 
@@ -470,9 +447,9 @@
   return uart->writeBlock(make_span(packet, packetLen));
 }
 
-error_code DS2480B::setLevel(Level newLevel) {
+Result<void> DS2480B::setLevel(Level newLevel) {
   if (level == newLevel) {
-    return error_code();
+    return none;
   }
 
   uint_least8_t packet[2];
@@ -497,33 +474,27 @@
     break;
 
   default:
-    return make_error_code(InvalidLevelError);
+    return InvalidLevelError;
   }
 
   // Send the packet.
-  error_code result = uart->writeBlock(make_span(packet, packetLen));
-  if (result) {
-    return result;
-  }
+  TRY(uart->writeBlock(make_span(packet, packetLen)));
 
   if (newLevel == NormalLevel) {
     // Read back the response.
-    result = uart->readByte(packet[0]);
-    if (result) {
-      return result;
-    }
+    TRY_VALUE(packet[0], uart->readByte());
 
     // Interpret the response.
     if ((packet[0] & 0xE0) != 0xE0) {
-      return make_error_code(HardwareError);
+      return HardwareError;
     }
   }
 
   level = newLevel;
-  return result;
+  return none;
 }
 
-error_code DS2480B::sendCommand(uint_least8_t command) {
+Result<void> DS2480B::sendCommand(uint_least8_t command) {
   uint_least8_t packet[2];
   int packetLen = 0;
 
@@ -549,10 +520,8 @@
       switch (condition) {
       case HardwareError:
         return "Hardware Error";
-
-      default:
-        return defaultErrorMessage(condition);
       }
+      return defaultErrorMessage(condition);
     }
   } instance;
   return instance;
--- a/MaximInterfaceDevices/DS2480B.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS2480B.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceDevices_DS2480B
-#define MaximInterfaceDevices_DS2480B
+#ifndef MaximInterfaceDevices_DS2480B_hpp
+#define MaximInterfaceDevices_DS2480B_hpp
 
 #include <MaximInterfaceCore/OneWireMaster.hpp>
 #include <MaximInterfaceCore/Sleep.hpp>
@@ -52,30 +52,30 @@
 
   void setUart(Core::Uart & uart) { this->uart = &uart; }
 
-  MaximInterfaceDevices_EXPORT Core::error_code initialize();
+  MaximInterfaceDevices_EXPORT Core::Result<void> initialize();
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code reset();
+  MaximInterfaceDevices_EXPORT virtual Core::Result<void> reset();
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
-  touchBitSetLevel(bool & sendRecvBit, Level afterLevel);
+  MaximInterfaceDevices_EXPORT virtual Core::Result<bool>
+  touchBitSetLevel(bool sendBit, Level afterLevel);
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  MaximInterfaceDevices_EXPORT virtual Core::Result<void>
   writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
-  readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+  MaximInterfaceDevices_EXPORT virtual Core::Result<uint_least8_t>
+  readByteSetLevel(Level afterLevel);
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  MaximInterfaceDevices_EXPORT virtual Core::Result<void>
   setSpeed(Speed newSpeed);
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  MaximInterfaceDevices_EXPORT virtual Core::Result<void>
   setLevel(Level newLevel);
 
   MaximInterfaceDevices_EXPORT static const Core::error_category &
   errorCategory();
 
 protected:
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   sendCommand(uint_least8_t command);
 
 private:
@@ -87,6 +87,16 @@
   uint_least8_t speed;
 };
 
+} // namespace MaximInterfaceDevices
+namespace MaximInterfaceCore {
+
+template <>
+struct is_error_code_enum<MaximInterfaceDevices::DS2480B::ErrorValue>
+    : true_type {};
+
+} // namespace MaximInterfaceCore
+namespace MaximInterfaceDevices {
+
 inline Core::error_code make_error_code(DS2480B::ErrorValue e) {
   return Core::error_code(e, DS2480B::errorCategory());
 }
--- a/MaximInterfaceDevices/DS2482_DS2484.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS2482_DS2484.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -33,60 +33,50 @@
 #include <MaximInterfaceCore/Error.hpp>
 #include "DS2482_DS2484.hpp"
 
+#define TRY MaximInterfaceCore_TRY
+#define TRY_VALUE MaximInterfaceCore_TRY_VALUE
+
 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
-};
+// Device status bits.
+static const uint_least8_t status_1WB = 0x01;
+static const uint_least8_t status_PPD = 0x02;
+static const uint_least8_t status_SD = 0x04;
+static const uint_least8_t status_SBR = 0x20;
+static const uint_least8_t status_TSB = 0x40;
+static const uint_least8_t status_DIR = 0x80;
 
-error_code DS2482_DS2484::initialize(Config config) {
-  error_code result = resetDevice();
-  if (result) {
-    return result;
-  }
+Result<void> DS2482_DS2484::initialize(Config config) {
+  TRY(resetDevice());
   // Write the default configuration setup.
-  result = writeConfig(config);
-  return result;
+  TRY(writeConfig(config));
+  return none;
 }
 
-error_code DS2482_DS2484::resetDevice() {
+Result<void> 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;
-  }
+  TRY(sendCommand(0xF0));
 
   uint_least8_t buf;
-  result = readRegister(buf);
-  if (result) {
-    return result;
-  }
+  TRY_VALUE(buf, readRegister());
 
   if ((buf & 0xF7) != 0x10) {
-    return make_error_code(HardwareError);
+    return HardwareError;
   }
 
   // Do a command to get 1-Wire master reset out of holding state.
   reset();
 
-  return result;
+  return none;
 }
 
-error_code DS2482_DS2484::triplet(TripletData & data) {
+Result<OneWireMaster::TripletData> DS2482_DS2484::triplet(bool sendBit) {
   // 1-Wire Triplet (Case B)
   //   S AD,0 [A] 1WT [A] SS [A] Sr AD,1 [A] [Status] A [Status] A\ P
   //                                         \--------/
@@ -94,48 +84,41 @@
   //  [] 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;
+  TRY(sendCommand(0x78, sendBit ? 0x80 : 0x00));
+
+  uint_least8_t status;
+  TRY_VALUE(status, pollBusy());
+
+  TripletData data;
+  data.readBit = ((status & status_SBR) == status_SBR);
+  data.readBitComplement = ((status & status_TSB) == status_TSB);
+  data.writeBit = ((status & status_DIR) == status_DIR);
+  return data;
 }
 
-error_code DS2482_DS2484::reset() {
+Result<void> 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;
-  }
+  TRY(sendCommand(0xB4));
+
+  uint_least8_t status;
+  TRY_VALUE(status, pollBusy());
 
-  uint_least8_t buf;
-  result = pollBusy(&buf);
-  if (result) {
-    return result;
+  if ((status & status_SD) == status_SD) {
+    return ShortDetectedError;
+  }
+  if ((status & status_PPD) != status_PPD) {
+    return NoSlaveError;
   }
 
-  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;
+  return none;
 }
 
-error_code DS2482_DS2484::touchBitSetLevel(bool & sendRecvBit,
-                                           Level afterLevel) {
+Result<bool> DS2482_DS2484::touchBitSetLevel(bool sendBit, Level afterLevel) {
   // 1-Wire bit (Case B)
   //   S AD,0 [A] 1WSB [A] BB [A] Sr AD,1 [A] [Status] A [Status] A\ P
   //                                          \--------/
@@ -143,26 +126,15 @@
   //  [] 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;
-  }
-
+  TRY(configureLevel(afterLevel));
+  TRY(sendCommand(0x87, sendBit ? 0x80 : 0x00));
   uint_least8_t status;
-  result = pollBusy(&status);
-  if (!result) {
-    sendRecvBit = ((status & Status_SBR) == Status_SBR);
-  }
-  return result;
+  TRY_VALUE(status, pollBusy());
+  return (status & status_SBR) == status_SBR;
 }
 
-error_code DS2482_DS2484::writeByteSetLevel(uint_least8_t sendByte,
-                                            Level afterLevel) {
+Result<void> 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
   //                                          \--------/
@@ -170,22 +142,13 @@
   //  [] 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;
+  TRY(configureLevel(afterLevel));
+  TRY(sendCommand(0xA5, sendByte));
+  TRY(pollBusy());
+  return none;
 }
 
-error_code DS2482_DS2484::readByteSetLevel(uint_least8_t & recvByte,
-                                           Level afterLevel) {
+Result<uint_least8_t> DS2482_DS2484::readByteSetLevel(Level afterLevel) {
   // 1-Wire Read Bytes (Case C)
   //   S AD,0 [A] 1WRB [A] Sr AD,1 [A] [Status] A [Status] A
   //                                   \--------/
@@ -195,119 +158,94 @@
   //  [] 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;
+  TRY(configureLevel(afterLevel));
+  TRY(sendCommand(0x96));
+  TRY(pollBusy());
+  return readRegister(0xE1);
 }
 
-error_code DS2482_DS2484::setSpeed(Speed newSpeed) {
+Result<void> DS2482_DS2484::setSpeed(Speed newSpeed) {
   // Check if supported speed
   if (!((newSpeed == OverdriveSpeed) || (newSpeed == StandardSpeed))) {
-    return make_error_code(InvalidSpeedError);
+    return InvalidSpeedError;
   }
   // Check if requested speed is already set
   if (curConfig.get1WS() == (newSpeed == OverdriveSpeed)) {
-    return error_code();
+    return none;
   }
   // Set the speed
   return writeConfig(Config(curConfig).set1WS(newSpeed == OverdriveSpeed));
 }
 
-error_code DS2482_DS2484::setLevel(Level newLevel) {
+Result<void> DS2482_DS2484::setLevel(Level newLevel) {
   if (newLevel == StrongLevel) {
-    return make_error_code(InvalidLevelError);
+    return InvalidLevelError;
   }
 
   return configureLevel(newLevel);
 }
 
-error_code DS2482_DS2484::writeConfig(Config config) {
+Result<void> 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);
+  TRY(sendCommand(0xD2, configBuf));
+
+  TRY_VALUE(configBuf, readRegister(0xC3));
+
+  if (configBuf != config.readByte()) {
+    return HardwareError;
   }
-  if (!result) {
-    if (configBuf != config.readByte()) {
-      result = make_error_code(HardwareError);
-    }
-  }
-  if (!result) {
-    curConfig = config;
-  }
-  return result;
+
+  curConfig = config;
+  return none;
 }
 
-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;
+Result<uint_least8_t> DS2482_DS2484::readRegister(uint_least8_t reg) const {
+  TRY(sendCommand(0xE1, reg));
+  return readRegister();
 }
 
-error_code DS2482_DS2484::readRegister(uint_least8_t & buf) const {
-  return master->readPacket(address_, make_span(&buf, 1));
+Result<uint_least8_t> DS2482_DS2484::readRegister() const {
+  uint_least8_t buf;
+  TRY(master->readPacket(address_, make_span(&buf, 1), I2CMaster::Stop));
+  return buf;
 }
 
-error_code DS2482_DS2484::pollBusy(uint_least8_t * pStatus) {
+Result<uint_least8_t> DS2482_DS2484::pollBusy() {
   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;
+    TRY_VALUE(status, readRegister());
+    if (pollCount++ >= pollLimit) {
+      return HardwareError;
     }
-    if (pollCount++ >= pollLimit) {
-      return make_error_code(HardwareError);
-    }
-  } while (status & Status_1WB);
-
-  return error_code();
+  } while ((status & status_1WB) == status_1WB);
+  return status;
 }
 
-error_code DS2482_DS2484::configureLevel(Level level) {
+Result<void> DS2482_DS2484::configureLevel(Level level) {
   // Check if supported level
   if (!((level == NormalLevel) || (level == StrongLevel))) {
-    return make_error_code(InvalidLevelError);
+    return InvalidLevelError;
   }
   // Check if requested level already set
   if (curConfig.getSPU() == (level == StrongLevel)) {
-    return error_code();
+    return none;
   }
   // 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));
+Result<void> DS2482_DS2484::sendCommand(uint_least8_t cmd) const {
+  return master->writePacket(address_, make_span(&cmd, 1), I2CMaster::Stop);
 }
 
-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);
+Result<void> DS2482_DS2484::sendCommand(uint_least8_t cmd,
+                                        uint_least8_t param) const {
+  const uint_least8_t buf[] = {cmd, param};
+  return master->writePacket(address_, buf, I2CMaster::Stop);
 }
 
 const error_category & DS2482_DS2484::errorCategory() {
@@ -322,16 +260,14 @@
 
       case ArgumentOutOfRangeError:
         return "Argument Out of Range Error";
-
-      default:
-        return defaultErrorMessage(condition);
       }
+      return defaultErrorMessage(condition);
     }
   } instance;
   return instance;
 }
 
-error_code DS2482_800::selectChannel(int channel) {
+Result<void> 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
@@ -382,45 +318,35 @@
     break;
 
   default:
-    return make_error_code(ArgumentOutOfRangeError);
+    return 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);
-      }
-    }
+  TRY(sendCommand(0xC3, ch));
+  TRY_VALUE(ch, readRegister());
+  // check for failure due to incorrect read back of channel
+  if (ch != ch_read) {
+    return HardwareError;
   }
 
-  return result;
+  return none;
 }
 
-error_code DS2484::adjustPort(PortParameter param, int val) {
+Result<void> DS2484::adjustPort(PortParameter param, int val) {
   if (val < 0 || val > 15) {
-    return make_error_code(ArgumentOutOfRangeError);
+    return ArgumentOutOfRangeError;
   }
 
-  error_code result = sendCommand(0xC3, (param << 4) | val);
-  if (result) {
-    return result;
-  }
+  TRY(sendCommand(0xC3, (param << 4) | val));
 
   uint_least8_t portConfig = val + 1;
   for (int reads = -1; reads < param; ++reads) {
-    result = readRegister(portConfig);
-    if (result) {
-      return result;
-    }
+    TRY_VALUE(portConfig, readRegister());
   }
   if (val != portConfig) {
-    result = make_error_code(HardwareError);
+    return HardwareError;
   }
 
-  return result;
+  return none;
 }
 
 } // namespace MaximInterfaceDevices
--- a/MaximInterfaceDevices/DS2482_DS2484.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS2482_DS2484.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceDevices_DS2482_DS2484
-#define MaximInterfaceDevices_DS2482_DS2484
+#ifndef MaximInterfaceDevices_DS2482_DS2484_hpp
+#define MaximInterfaceDevices_DS2482_DS2484_hpp
 
 #include <MaximInterfaceCore/I2CMaster.hpp>
 #include <MaximInterfaceCore/OneWireMaster.hpp>
@@ -146,31 +146,31 @@
   void setAddress(uint_least8_t address) { address_ = address; }
 
   /// Initialize hardware for use.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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 Core::Result<void> writeConfig(Config config);
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
-  triplet(TripletData & data);
+  MaximInterfaceDevices_EXPORT virtual Core::Result<TripletData>
+  triplet(bool sendBit);
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code reset();
+  MaximInterfaceDevices_EXPORT virtual Core::Result<void> reset();
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
-  touchBitSetLevel(bool & sendRecvBit, Level afterLevel);
+  MaximInterfaceDevices_EXPORT virtual Core::Result<bool>
+  touchBitSetLevel(bool sendBit, Level afterLevel);
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
-  readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+  MaximInterfaceDevices_EXPORT virtual Core::Result<uint_least8_t>
+  readByteSetLevel(Level afterLevel);
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  MaximInterfaceDevices_EXPORT virtual Core::Result<void>
   writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  MaximInterfaceDevices_EXPORT virtual Core::Result<void>
   setSpeed(Speed newSpeed);
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  MaximInterfaceDevices_EXPORT virtual Core::Result<void>
   setLevel(Level newLevel);
 
   MaximInterfaceDevices_EXPORT static const Core::error_category &
@@ -181,40 +181,49 @@
       : master(&master), address_(address) {}
 
   /// @note Allow marking const since not public.
-  Core::error_code sendCommand(uint_least8_t cmd) const;
+  Core::Result<void> 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;
+  Core::Result<void> 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;
+  /// @returns Read data from register.
+  Core::Result<uint_least8_t> readRegister(uint_least8_t reg) 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;
+  /// @returns Read data from register.
+  Core::Result<uint_least8_t> readRegister() const;
 
 private:
   /// @brief Performs a soft reset on the device.
   /// @note This is not a 1-Wire Reset.
-  Core::error_code resetDevice();
+  Core::Result<void> 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);
+  /// @returns Status byte or TimeoutError if poll limit reached.
+  Core::Result<uint_least8_t> pollBusy();
 
   /// @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::Result<void> configureLevel(Level level);
 
   Core::I2CMaster * master;
   uint_least8_t address_;
   Config curConfig;
 };
 
+} // namespace MaximInterfaceDevices
+namespace MaximInterfaceCore {
+
+template <>
+struct is_error_code_enum<MaximInterfaceDevices::DS2482_DS2484::ErrorValue>
+    : true_type {};
+
+} // namespace MaximInterfaceCore
+namespace MaximInterfaceDevices {
+
 inline Core::error_code make_error_code(DS2482_DS2484::ErrorValue e) {
   return Core::error_code(e, DS2482_DS2484::errorCategory());
 }
@@ -233,7 +242,7 @@
 
   /// @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);
+  MaximInterfaceDevices_EXPORT Core::Result<void> selectChannel(int channel);
 };
 
 /// DS2484 I2C to 1-Wire Master
@@ -258,8 +267,8 @@
   /// @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);
+  MaximInterfaceDevices_EXPORT Core::Result<void>
+  adjustPort(PortParameter param, int val);
 };
 
 } // namespace MaximInterfaceDevices
--- a/MaximInterfaceDevices/DS28C36_DS2476.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS28C36_DS2476.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -36,21 +36,22 @@
 #include <MaximInterfaceCore/RomId.hpp>
 #include "DS28C36_DS2476.hpp"
 
+#define TRY MaximInterfaceCore_TRY
+#define TRY_VALUE MaximInterfaceCore_TRY_VALUE
+
 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;
+static Result<void> convertResultByte(uint_least8_t resultByte) {
+  return (resultByte == 0xAA)
+             ? makeResult(none)
+             : error_code((resultByte == 0x00)
+                              ? static_cast<int>(DS28C36::AuthenticationError)
+                              : resultByte,
+                          DS28C36::errorCategory());
 }
 
 const int DS28C36::publicKeyAxPage;
@@ -71,166 +72,178 @@
 const int DS28C36::publicKeySyPage;
 const int DS28C36::memoryPages;
 
-error_code DS28C36::writeMemory(int pageNum, Page::const_span page) {
+Result<void> DS28C36::writeMemory(int pageNum, Page::const_span page) {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   uint_least8_t buffer[1 + Page::size];
   buffer[0] = pageNum;
   copy(page.begin(), page.end(), buffer + 1);
-  error_code result = writeCommand(0x96, buffer);
+  Result<void> result = writeCommand(0x96, buffer);
   if (!result) {
-    sleep(writeMemoryTimeMs);
-    result = readFixedLengthResponse(make_span(buffer, 1));
-    if (!result) {
-      result = convertResultByte(buffer[0]);
-    }
+    return result;
   }
+  sleep(writeMemoryTimeMs);
+  result = readFixedLengthResponse(make_span(buffer, 1));
+  if (!result) {
+    return result;
+  }
+  result = convertResultByte(buffer[0]);
   return result;
 }
 
-error_code DS28C36::readMemory(int pageNum, Page::span page) {
+Result<DS28C36::Page::array> DS28C36::readMemory(int pageNum) const {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const uint_least8_t parameter = pageNum;
-  error_code result = writeCommand(0x69, make_span(&parameter, 1));
+  Result<void> result = writeCommand(0x69, make_span(&parameter, 1));
+  if (!result) {
+    return result.error();
+  }
+  sleep(readMemoryTimeMs);
+  array<uint_least8_t, 1 + Page::size> response;
+  result = readFixedLengthResponse(response);
   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();
   }
-  return result;
+  result = convertResultByte(response[0]);
+  if (!result) {
+    return result.error();
+  }
+  Page::array page;
+  copy(response.begin() + 1, response.end(), page.begin());
+  return page;
 }
 
-error_code DS28C36::writeBuffer(span<const uint_least8_t> data) {
+Result<void> 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;
+Result<std::vector<uint_least8_t> > DS28C36::readBuffer() const {
+  TRY(writeCommand(0x5A));
+  std::vector<uint_least8_t> buffer(80);
+  span<uint_least8_t>::index_type bufferLength;
+  TRY_VALUE(bufferLength, readVariableLengthResponse(buffer));
+  buffer.resize(bufferLength);
+  return buffer;
 }
 
-error_code DS28C36::readPageProtection(int pageNum,
-                                       PageProtection & protection) {
+Result<DS28C36::PageProtection> DS28C36::readPageProtection(int pageNum) const {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   uint_least8_t buffer = pageNum;
-  error_code result = writeCommand(0xAA, make_span(&buffer, 1));
+  Result<void> result = writeCommand(0xAA, make_span(&buffer, 1));
   if (!result) {
-    sleep(readMemoryTimeMs);
-    result = readFixedLengthResponse(make_span(&buffer, 1));
-    if (!result) {
-      protection = buffer;
-    }
+    return result.error();
   }
-  return result;
+  sleep(readMemoryTimeMs);
+  result = readFixedLengthResponse(make_span(&buffer, 1));
+  if (!result) {
+    return result.error();
+  }
+  return PageProtection(buffer);
 }
 
-error_code DS28C36::setPageProtection(int pageNum,
-                                      const PageProtection & protection) {
+Result<void> DS28C36::setPageProtection(int pageNum,
+                                        const PageProtection & protection) {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return 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);
+  Result<void> result = writeCommand(0xC3, buffer);
   if (!result) {
-    sleep(writeMemoryTimeMs);
-    result = readFixedLengthResponse(make_span(buffer, 1));
-    if (!result) {
-      result = convertResultByte(buffer[0]);
-    }
+    return result;
   }
+  sleep(writeMemoryTimeMs);
+  result = readFixedLengthResponse(make_span(buffer, 1));
+  if (!result) {
+    return result;
+  }
+  result = convertResultByte(buffer[0]);
   return result;
 }
 
-error_code DS28C36::decrementCounter() {
-  error_code result = writeCommand(0xC9);
+Result<void> DS28C36::decrementCounter() {
+  Result<void> result = writeCommand(0xC9);
   if (!result) {
-    sleep(writeMemoryTimeMs);
-    uint_least8_t response;
-    result = readFixedLengthResponse(make_span(&response, 1));
-    if (!result) {
-      result = convertResultByte(response);
-    }
+    return result;
   }
+  sleep(writeMemoryTimeMs);
+  uint_least8_t response;
+  result = readFixedLengthResponse(make_span(&response, 1));
+  if (!result) {
+    return result;
+  }
+  result = convertResultByte(response);
   return result;
 }
 
-error_code DS28C36::readRng(span<uint_least8_t> data) {
+Result<void> DS28C36::readRng(span<uint_least8_t> data) const {
   if ((data.size() < 1) || (data.size() > 64)) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   data[0] = static_cast<uint_least8_t>(data.size() - 1);
-  error_code result = writeCommand(0xD2, data.first(1));
+  Result<void> result = writeCommand(0xD2, data.first(1));
   if (!result) {
-    sleep(sha256ComputationTimeMs);
-    result = readFixedLengthResponse(data);
+    return result;
   }
+  sleep(sha256ComputationTimeMs);
+  result = readFixedLengthResponse(data);
   return result;
 }
 
-error_code DS28C36::encryptedReadMemory(int pageNum, SecretNum secretNum,
-                                        EncryptionChallenge::span challenge,
-                                        Page::span data) {
+Result<std::pair<DS28C36::EncryptionChallenge::array, DS28C36::Page::array> >
+DS28C36::encryptedReadMemory(int pageNum, SecretNum secretNum) const {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const uint_least8_t parameter = (secretNum << 6) | pageNum;
-  error_code result = writeCommand(0x4B, make_span(&parameter, 1));
+  Result<void> result = writeCommand(0x4B, make_span(&parameter, 1));
+  if (!result) {
+    return result.error();
+  }
+  sleep(readMemoryTimeMs + sha256ComputationTimeMs);
+  uint_least8_t response[1 + EncryptionChallenge::size + Page::size];
+  result = readFixedLengthResponse(response);
   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();
+  }
+  result = convertResultByte(response[0]);
+  if (!result) {
+    return result.error();
   }
-  return result;
+  std::pair<DS28C36::EncryptionChallenge::array, DS28C36::Page::array> data;
+  const uint_least8_t * begin = response + 1;
+  const uint_least8_t * end = begin + data.first.size();
+  copy(begin, end, data.first.begin());
+  begin = end;
+  end = begin + data.second.size();
+  copy(begin, end, data.second.begin());
+  return data;
 }
 
-error_code DS28C36::computeAndReadPageAuthentication(int pageNum,
-                                                     AuthType authType) {
+Result<void>
+DS28C36::computeAndReadPageAuthentication(int pageNum,
+                                          AuthType authType) const {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return 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) {
+Result<Signature::array>
+DS28C36::computeAndReadPageAuthentication(int pageNum, KeyNum keyNum) const {
   AuthType authType;
   switch (keyNum) {
   case KeyNumA:
@@ -243,29 +256,35 @@
     authType = EcdsaWithKeyC;
     break;
   default:
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
-  error_code result = computeAndReadPageAuthentication(pageNum, authType);
+  Result<void> result = computeAndReadPageAuthentication(pageNum, authType);
+  if (!result) {
+    return result.error();
+  }
+  sleep(readMemoryTimeMs + generateEcdsaSignatureTimeMs);
+  uint_least8_t response[1 + 2 * Scalar::size];
+  result = readFixedLengthResponse(response);
   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();
+  }
+  result = convertResultByte(response[0]);
+  if (!result) {
+    return result.error();
   }
-  return result;
+  Signature::array signature;
+  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 signature;
 }
 
-error_code DS28C36::computeAndReadPageAuthentication(int pageNum,
-                                                     SecretNum secretNum,
-                                                     Page::span hmac) {
+Result<DS28C36::Page::array>
+DS28C36::computeAndReadPageAuthentication(int pageNum,
+                                          SecretNum secretNum) const {
   AuthType authType;
   switch (secretNum) {
   case SecretNumA:
@@ -278,93 +297,106 @@
     authType = HmacWithSecretS;
     break;
   default:
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
-  error_code result = computeAndReadPageAuthentication(pageNum, authType);
+  Result<void> result = computeAndReadPageAuthentication(pageNum, authType);
+  if (!result) {
+    return result.error();
+  }
+  sleep(readMemoryTimeMs + sha256ComputationTimeMs);
+  array<uint_least8_t, 1 + Page::size> response;
+  result = readFixedLengthResponse(response);
   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();
   }
-  return result;
+  result = convertResultByte(response[0]);
+  if (!result) {
+    return result.error();
+  }
+  Page::array hmac;
+  copy(response.begin() + 1, response.end(), hmac.begin());
+  return hmac;
 }
 
-error_code DS28C36::authenticatedSha2WriteMemory(int pageNum,
-                                                 SecretNum secretNum,
-                                                 Page::const_span page) {
+Result<void> DS28C36::authenticatedSha2WriteMemory(int pageNum,
+                                                   SecretNum secretNum,
+                                                   Page::const_span page) {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return 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);
+  Result<void> result = writeCommand(0x99, buffer);
   if (!result) {
-    sleep(writeMemoryTimeMs + (2 * sha256ComputationTimeMs));
-    result = readFixedLengthResponse(make_span(buffer, 1));
-    if (!result) {
-      result = convertResultByte(buffer[0]);
-    }
+    return result;
   }
+  sleep(writeMemoryTimeMs + (2 * sha256ComputationTimeMs));
+  result = readFixedLengthResponse(make_span(buffer, 1));
+  if (!result) {
+    return result;
+  }
+  result = convertResultByte(buffer[0]);
   return result;
 }
 
-error_code DS28C36::computeAndLockSha2Secret(int pageNum, SecretNum msecretNum,
-                                             SecretNum dsecretNum,
-                                             bool writeProtectEnable) {
+Result<void> DS28C36::computeAndLockSha2Secret(int pageNum,
+                                               SecretNum msecretNum,
+                                               SecretNum dsecretNum,
+                                               bool writeProtectEnable) {
   // User pages only
   if (pageNum < 0 || pageNum > 15) {
-    return make_error_code(InvalidParameterError);
+    return 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);
+  Result<void> 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;
   }
+  sleep(sha256ComputationTimeMs +
+        ((writeProtectEnable ? 2 : 1) * writeMemoryTimeMs));
+  result = readFixedLengthResponse(make_span(buffer, 1));
+  if (!result) {
+    return result;
+  }
+  result = convertResultByte(buffer[0]);
   return result;
 }
 
-error_code DS28C36::generateEcc256KeyPair(KeyNum keyNum,
-                                          bool writeProtectEnable) {
+Result<void> DS28C36::generateEcc256KeyPair(KeyNum keyNum,
+                                            bool writeProtectEnable) {
   if (keyNum == KeyNumS) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   uint_least8_t buffer = keyNum;
   if (writeProtectEnable) {
     buffer |= 0x80;
   }
-  error_code result = writeCommand(0xCB, make_span(&buffer, 1));
+  Result<void> result = writeCommand(0xCB, make_span(&buffer, 1));
   if (!result) {
-    sleep(generateEccKeyPairTimeMs);
-    result = readFixedLengthResponse(make_span(&buffer, 1));
-    if (!result) {
-      result = convertResultByte(buffer);
-    }
+    return result;
   }
+  sleep(generateEccKeyPairTimeMs);
+  result = readFixedLengthResponse(make_span(&buffer, 1));
+  if (!result) {
+    return result;
+  }
+  result = convertResultByte(buffer);
   return result;
 }
 
-error_code DS28C36::computeMultiblockHash(bool firstBlock, bool lastBlock,
-                                          span<const uint_least8_t> data) {
+Result<void> 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);
+    return InvalidParameterError;
   }
 
   uint_least8_t buffer[1 + maxDataSize];
@@ -376,20 +408,22 @@
     buffer[0] |= 0x80;
   }
   copy(data.begin(), data.end(), buffer + 1);
-  error_code result = writeCommand(0x33, make_span(buffer, data.size() + 1));
+  Result<void> 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;
   }
+  sleep(sha256ComputationTimeMs);
+  result = readFixedLengthResponse(make_span(buffer, 1));
+  if (!result) {
+    return result;
+  }
+  result = convertResultByte(buffer[0]);
   return result;
 }
 
-error_code DS28C36::verifyEcdsaSignature(KeyNum keyNum, HashType hashType,
-                                         Signature::const_span signature,
-                                         PioState pioa, PioState piob) {
+Result<void> 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) {
@@ -407,25 +441,27 @@
   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);
+  Result<void> 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;
   }
+  sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs +
+        ((hashType == DataInBuffer) ? sha256ComputationTimeMs : 0));
+  result = readFixedLengthResponse(make_span(buffer, 1));
+  if (!result) {
+    return result;
+  }
+  result = convertResultByte(buffer[0]);
   return result;
 }
 
-error_code
+Result<void>
 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);
+    return InvalidParameterError;
   }
 
   uint_least8_t buffer[1 + 2 * Scalar::size];
@@ -439,58 +475,62 @@
   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);
+  Result<void> 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;
   }
+  sleep((ecdh ? 2 : 1) * verifyEsdsaSignatureOrComputeEcdhTimeMs);
+  result = readFixedLengthResponse(make_span(buffer, 1));
+  if (!result) {
+    return result;
+  }
+  result = convertResultByte(buffer[0]);
   return result;
 }
 
-error_code DS28C36::authenticatedEcdsaWriteMemory(int pageNum,
-                                                  Page::const_span page) {
+Result<void> DS28C36::authenticatedEcdsaWriteMemory(int pageNum,
+                                                    Page::const_span page) {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   uint_least8_t buffer[1 + Page::size];
   buffer[0] = pageNum;
   copy(page.begin(), page.end(), buffer + 1);
-  error_code result = writeCommand(0x89, buffer);
+  Result<void> result = writeCommand(0x89, buffer);
   if (!result) {
-    sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs + writeMemoryTimeMs +
-          sha256ComputationTimeMs);
-    result = readFixedLengthResponse(make_span(buffer, 1));
-    if (!result) {
-      result = convertResultByte(buffer[0]);
-    }
+    return result;
   }
+  sleep(verifyEsdsaSignatureOrComputeEcdhTimeMs + writeMemoryTimeMs +
+        sha256ComputationTimeMs);
+  result = readFixedLengthResponse(make_span(buffer, 1));
+  if (!result) {
+    return 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) {
+Result<void> DS28C36::writeCommand(uint_least8_t command,
+                                   span<const uint_least8_t> parameters) const {
+  Result<void> result = master->start(address_);
+  if (!result) {
     master->stop();
     return result;
   }
   result = master->writeByte(command);
-  if (result) {
+  if (!result) {
     master->stop();
     return result;
   }
   if (!parameters.empty()) {
     result = master->writeByte(static_cast<uint_least8_t>(parameters.size()));
-    if (result) {
+    if (!result) {
       master->stop();
       return result;
     }
     result = master->writeBlock(parameters);
-    if (result) {
+    if (!result) {
       master->stop();
       return result;
     }
@@ -499,41 +539,44 @@
   return result;
 }
 
-error_code DS28C36::readVariableLengthResponse(span<uint_least8_t> & response) {
-  error_code result = master->start(address_ | 1);
-  if (result) {
+Result<span<uint_least8_t>::index_type>
+DS28C36::readVariableLengthResponse(span<uint_least8_t> response) const {
+  Result<void> result = master->start(address_ | 1);
+  if (!result) {
     master->stop();
-    return result;
+    return result.error();
   }
   uint_least8_t length;
-  result = master->readByte(I2CMaster::Ack, length);
-  if (result) {
+  if (const Result<uint_least8_t> result = master->readByte(I2CMaster::Ack)) {
+    length = result.value();
+  } else {
     master->stop();
-    return result;
+    return result.error();
   }
   if (length > response.size()) {
     master->stop();
-    return make_error_code(InvalidResponseError);
+    return InvalidResponseError;
   }
-  response = response.first(length);
-  if (!response.empty()) {
-    result = master->readBlock(I2CMaster::Nack, response);
-    if (result) {
+  if (length > 0) {
+    result = master->readBlock(response.first(length), I2CMaster::Nack);
+    if (!result) {
       master->stop();
-      return result;
+      return result.error();
     }
   }
   result = master->stop();
-  return result;
+  if (!result) {
+    return result.error();
+  }
+  return length;
 }
 
-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;
+Result<void>
+DS28C36::readFixedLengthResponse(span<uint_least8_t> response) const {
+  span<uint_least8_t>::index_type responseLength;
+  TRY_VALUE(responseLength, readVariableLengthResponse(response));
+  return (responseLength == response.size()) ? makeResult(none)
+                                             : InvalidResponseError;
 }
 
 const error_category & DS28C36::errorCategory() {
@@ -560,151 +603,146 @@
 
       case InvalidResponseError:
         return "Invalid Response Error";
-
-      default:
-        return defaultErrorMessage(condition);
       }
+      return defaultErrorMessage(condition);
     }
   } instance;
   return instance;
 }
 
-error_code DS2476::generateEcdsaSignature(KeyNum keyNum,
-                                          Signature::span signature) {
+Result<Signature::array> DS2476::generateEcdsaSignature(KeyNum keyNum) const {
   if (keyNum == KeyNumS) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const uint_least8_t parameter = keyNum;
-  error_code result = writeCommand(0x1E, make_span(&parameter, 1));
+  Result<void> result = writeCommand(0x1E, make_span(&parameter, 1));
+  if (!result) {
+    return result.error();
+  }
+  sleep(generateEcdsaSignatureTimeMs);
+  uint_least8_t response[1 + 2 * Scalar::size];
+  result = readFixedLengthResponse(response);
+  if (!result) {
+    return result.error();
+  }
+  result = convertResultByte(response[0]);
   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();
   }
+  Signature::array signature;
+  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 signature;
+}
+
+Result<void> DS2476::computeSha2UniqueSecret(SecretNum msecretNum) {
+  uint_least8_t buffer = msecretNum << 4;
+  Result<void> result = writeCommand(0x55, make_span(&buffer, 1));
+  if (!result) {
+    return result;
+  }
+  sleep(sha256ComputationTimeMs);
+  result = readFixedLengthResponse(make_span(&buffer, 1));
+  if (!result) {
+    return result;
+  }
+  result = convertResultByte(buffer);
   return result;
 }
 
-error_code DS2476::computeSha2UniqueSecret(SecretNum msecretNum) {
-  uint_least8_t buffer = msecretNum << 4;
-  error_code result = writeCommand(0x55, make_span(&buffer, 1));
+Result<DS2476::Page::array> DS2476::computeSha2Hmac() const {
+  Result<void> result = writeCommand(0x2D);
+  if (!result) {
+    return result.error();
+  }
+  sleep(sha256ComputationTimeMs);
+  array<uint_least8_t, 1 + Page::size> response;
+  result = readFixedLengthResponse(response);
   if (!result) {
-    sleep(sha256ComputationTimeMs);
-    result = readFixedLengthResponse(make_span(&buffer, 1));
-    if (!result) {
-      convertResultByte(buffer);
-    }
+    return result.error();
   }
-  return result;
+  result = convertResultByte(response[0]);
+  if (!result) {
+    return result.error();
+  }
+  Page::array hmac;
+  copy(response.begin() + 1, response.end(), hmac.begin());
+  return hmac;
 }
 
-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;
+Result<void> computeMultiblockHash(DS28C36 & ds28c36,
+                                   span<const uint_least8_t> data) {
   span<const uint_least8_t>::index_type dataIdx = 0;
-  while (dataIdx < data.size() && !result) {
+  while (dataIdx < data.size()) {
     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));
+    TRY(ds28c36.computeMultiblockHash(dataIdx == 0, remainingSize == chunkSize,
+                                      data.subspan(dataIdx, chunkSize)));
     dataIdx += chunkSize;
   }
-  return result;
+  return none;
 }
 
-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<void> verifyEcdsaSignature(DS28C36 & ds28c36, DS28C36::KeyNum publicKey,
+                                  span<const uint_least8_t> data,
+                                  Signature::const_span signature,
+                                  DS28C36::PioState pioa,
+                                  DS28C36::PioState piob) {
+  Result<void> 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 =
+Result<void> verifyEcdsaSignature(DS28C36 & ds28c36,
+                                  PublicKey::const_span publicKey,
+                                  span<const uint_least8_t> data,
+                                  Signature::const_span signature,
+                                  DS28C36::PioState pioa,
+                                  DS28C36::PioState piob) {
+  Result<void> result =
       ds28c36.writeMemory(DS28C36::publicKeySxPage, publicKey.x);
   if (!result) {
-    result = ds28c36.writeMemory(DS28C36::publicKeySyPage, publicKey.y);
+    return result;
   }
+  result = ds28c36.writeMemory(DS28C36::publicKeySyPage, publicKey.y);
   if (!result) {
-    result = verifyEcdsaSignature(ds28c36, DS28C36::KeyNumS, data, signature,
-                                  pioa, piob);
+    return 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);
+Result<void> enableCoprocessor(DS2476 & ds2476) {
+  DS2476::Page::array page;
+  TRY_VALUE(page, ds2476.readMemory(DS2476::gpioControlPage));
+  DS2476::GpioControl gpioControl(page);
+  if (!gpioControl.pioaConducting()) {
+    gpioControl.setPioaConducting(true);
+    TRY(ds2476.writeMemory(DS2476::gpioControlPage, page));
   }
-  return result;
+  return none;
 }
 
-error_code enableCoprocessor(DS2476 & ds2476) {
+Result<void> enableRomId(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);
-    }
+  TRY_VALUE(page, ds2476.readMemory(DS2476::romOptionsPage));
+  DS2476::RomOptions romOptions(page);
+  if (!romOptions.romBlockDisable()) {
+    romOptions.setRomBlockDisable(true);
+    TRY(ds2476.writeMemory(DS2476::romOptionsPage, 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;
+  return none;
 }
 
 static void setAnonymous(RomId::span romId) {
--- a/MaximInterfaceDevices/DS28C36_DS2476.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS28C36_DS2476.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,10 +30,11 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceDevices_DS28C36_DS2476
-#define MaximInterfaceDevices_DS28C36_DS2476
+#ifndef MaximInterfaceDevices_DS28C36_DS2476_hpp
+#define MaximInterfaceDevices_DS28C36_DS2476_hpp
 
 #include <stdint.h>
+#include <utility>
 #include <vector>
 #include <MaximInterfaceCore/Algorithm.hpp>
 #include <MaximInterfaceCore/array_span.hpp>
@@ -154,77 +155,74 @@
   /// @brief Write memory with no protection.
   /// @param pageNum Number of page to write.
   /// @param page Data to write.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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);
+  /// @returns Data that was read.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array>
+  readMemory(int pageNum) const;
 
   /// @brief Write the temporary buffer.
   /// @param data Data to write.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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);
+  /// @returns Data that was read.
+  MaximInterfaceDevices_EXPORT Core::Result<std::vector<uint_least8_t> >
+  readBuffer() const;
 
   /// @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);
+  /// @returns Protection that was read.
+  MaximInterfaceDevices_EXPORT Core::Result<PageProtection>
+  readPageProtection(int pageNum) const;
 
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   setPageProtection(int pageNum, const PageProtection & protection);
 
   /// Decrement the decrement-only counter.
-  MaximInterfaceDevices_EXPORT Core::error_code decrementCounter();
+  MaximInterfaceDevices_EXPORT Core::Result<void> 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);
+  MaximInterfaceDevices_EXPORT Core::Result<void>
+  readRng(Core::span<uint_least8_t> data) const;
 
   /// @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);
+  /// @returns Encryption challenge and encrypted page data that was read.
+  MaximInterfaceDevices_EXPORT
+      Core::Result<std::pair<EncryptionChallenge::array, Page::array> >
+      encryptedReadMemory(int pageNum, SecretNum secretNum) const;
 
   /// @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);
+  /// @returns Computed page signature.
+  MaximInterfaceDevices_EXPORT Core::Result<Core::Ecc256::Signature::array>
+  computeAndReadPageAuthentication(int pageNum, KeyNum keyNum) const;
 
   /// @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);
+  /// @returns Computed page HMAC.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array>
+  computeAndReadPageAuthentication(int pageNum, SecretNum secretNum) const;
 
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   authenticatedSha2WriteMemory(int pageNum, SecretNum secretNum,
                                Page::const_span page);
 
@@ -234,14 +232,14 @@
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   generateEcc256KeyPair(KeyNum keyNum, bool writeProtectEnable);
 
   /// @brief Compute a hash over multiple blocks.
@@ -249,7 +247,7 @@
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   computeMultiblockHash(bool firstBlock, bool lastBlock,
                         Core::span<const uint_least8_t> data);
 
@@ -259,7 +257,7 @@
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   verifyEcdsaSignature(KeyNum keyNum, HashType hashType,
                        Core::Ecc256::Signature::const_span signature,
                        PioState pioa = Unchanged, PioState piob = Unchanged);
@@ -273,7 +271,7 @@
   /// 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   authenticateEcdsaPublicKey(bool authWrites, bool ecdh, KeyNum keyNum,
                              int csOffset,
                              Core::Ecc256::Signature::const_span signature);
@@ -281,7 +279,7 @@
   /// @brief Write with ECDSA authentication.
   /// @param pageNum Number of page to write.
   /// @param page Data to write.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   authenticatedEcdsaWriteMemory(int pageNum, Page::const_span page);
 
   MaximInterfaceDevices_EXPORT static const Core::error_category &
@@ -296,17 +294,19 @@
   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::Result<void>
+  writeCommand(uint_least8_t command,
+               Core::span<const uint_least8_t> parameters) const;
 
-  Core::error_code writeCommand(uint_least8_t command) {
+  Core::Result<void> writeCommand(uint_least8_t command) const {
     return writeCommand(command, Core::span<const uint_least8_t>());
   }
 
-  Core::error_code
-  readVariableLengthResponse(Core::span<uint_least8_t> & response);
+  Core::Result<Core::span<uint_least8_t>::index_type>
+  readVariableLengthResponse(Core::span<uint_least8_t> response) const;
 
-  Core::error_code readFixedLengthResponse(Core::span<uint_least8_t> response);
+  Core::Result<void>
+  readFixedLengthResponse(Core::span<uint_least8_t> response) const;
 
   void sleep(int ms) const { sleep_->invoke(ms); }
 
@@ -320,12 +320,12 @@
     EcdsaWithKeyC = 5
   };
 
+  Core::Result<void> computeAndReadPageAuthentication(int pageNum,
+                                                      AuthType authType) const;
+
   const Core::Sleep * sleep_;
   Core::I2CMaster * master;
   uint_least8_t address_;
-
-  Core::error_code computeAndReadPageAuthentication(int pageNum,
-                                                    AuthType authType);
 };
 
 /// Interface to the DS2476 coprocessor.
@@ -339,22 +339,31 @@
   /// @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);
+  /// @returns Computed signature.
+  MaximInterfaceDevices_EXPORT Core::Result<Core::Ecc256::Signature::array>
+  generateEcdsaSignature(KeyNum keyNum) const;
 
   /// @brief Compute unique SHA2 secret.
   /// @param msecretNum Master secret to use in computation.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   computeSha2UniqueSecret(SecretNum msecretNum);
 
   /// @brief Compute SHA2 HMAC.
-  /// @param[out] hmac Computed HMAC.
-  MaximInterfaceDevices_EXPORT Core::error_code
-  computeSha2Hmac(Page::span hmac);
+  /// @returns Computed HMAC.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array>
+  computeSha2Hmac() const;
 };
 
+} // namespace MaximInterfaceDevices
+namespace MaximInterfaceCore {
+
+template <>
+struct is_error_code_enum<MaximInterfaceDevices::DS28C36::ErrorValue>
+    : true_type {};
+
+} // namespace MaximInterfaceCore
+namespace MaximInterfaceDevices {
+
 inline Core::error_code make_error_code(DS28C36::ErrorValue e) {
   return Core::error_code(e, DS28C36::errorCategory());
 }
@@ -363,7 +372,7 @@
 /// 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
+MaximInterfaceDevices_EXPORT Core::Result<void>
 computeMultiblockHash(DS28C36 & ds28c36, Core::span<const uint_least8_t> data);
 
 /// @brief Verify ECDSA signature.
@@ -373,7 +382,7 @@
 /// @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
+MaximInterfaceDevices_EXPORT Core::Result<void>
 verifyEcdsaSignature(DS28C36 & ds28c36, DS28C36::KeyNum publicKey,
                      Core::span<const uint_least8_t> data,
                      Core::Ecc256::Signature::const_span signature,
@@ -388,7 +397,7 @@
 /// @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
+MaximInterfaceDevices_EXPORT Core::Result<void>
 verifyEcdsaSignature(DS28C36 & ds28c36,
                      Core::Ecc256::PublicKey::const_span publicKey,
                      Core::span<const uint_least8_t> data,
@@ -397,25 +406,15 @@
                      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
+MaximInterfaceDevices_EXPORT Core::Result<void>
 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);
+MaximInterfaceDevices_EXPORT Core::Result<void> enableRomId(DS2476 & ds2476);
 
 /// Format page authentication input data.
 class DS28C36::PageAuthenticationData {
@@ -536,13 +535,11 @@
   /// @}
 
 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;
+  static const size_t romIdIdx = 0;
+  static const size_t pageIdx = romIdIdx + Core::RomId::size;
+  static const size_t challengeIdx = pageIdx + Page::size;
+  static const size_t pageNumIdx = challengeIdx + Page::size;
+  static const size_t manIdIdx = pageNumIdx + 1;
 
   Result::array result_;
 };
@@ -855,13 +852,11 @@
   /// @}
 
 private:
-  typedef Result::span::index_type index;
-
-  static const index encryptionChallengeIdx = 0;
-  static const index romIdIdx =
+  static const size_t encryptionChallengeIdx = 0;
+  static const size_t romIdIdx =
       encryptionChallengeIdx + EncryptionChallenge::size;
-  static const index pageNumIdx = romIdIdx + Core::RomId::size;
-  static const index manIdIdx = pageNumIdx + 1;
+  static const size_t pageNumIdx = romIdIdx + Core::RomId::size;
+  static const size_t manIdIdx = pageNumIdx + 1;
 
   Result::array result_;
 };
--- a/MaximInterfaceDevices/DS28C39.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS28C39.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -55,9 +55,9 @@
 const int DS28C39::writePublicKeyYPage;
 const int DS28C39::memoryPages;
 
-error_code DS28C39::writeMemory(int pageNum, Page::const_span page) {
+Result<void> DS28C39::writeMemory(int pageNum, Page::const_span page) {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   uint_least8_t request[2 + Page::size];
@@ -67,72 +67,74 @@
   return runCommand(request, writeMemoryTimeMs);
 }
 
-error_code DS28C39::readMemory(int pageNum, Page::span page) {
+Result<DS28C39::Page::array> DS28C39::readMemory(int pageNum) const {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return 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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, 2), readMemoryTimeMs, buffer);
+  if (!response) {
+    return response.error();
   }
-  return result;
+  Page::array page;
+  copy(response.value().begin(), response.value().end(), page.begin());
+  return page;
 }
 
-error_code DS28C39::readStatus(bool entropyHealthTest, Status & status) {
+Result<DS28C39::Status> DS28C39::readStatus(bool entropyHealthTest) const {
   int delay = readMemoryTimeMs;
   if (entropyHealthTest) {
     delay += trngOnDemandCheckTimeMs;
   }
-  uint_least8_t buffer[Status::PageProtectionList::csize + RomId::size +
-                       ManId::size + Status::RomVersion::csize + 2];
+  uint_least8_t buffer[Status::PageProtectionList::size + RomId::size +
+                       ManId::size + Status::RomVersion::size + 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;
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, 2), delay, buffer);
+  if (!response) {
+    return response.error();
+  }
+  Status status;
+  span<uint_least8_t>::const_iterator responseIt = response.value().begin();
+  for (Status::PageProtectionList::array::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;
-    }
+  default:
+    return InvalidResponseError;
   }
-  return result;
+  return status;
 }
 
-error_code DS28C39::setPageProtection(int pageNum,
-                                      const PageProtection & protection) {
+Result<void> DS28C39::setPageProtection(int pageNum,
+                                        const PageProtection & protection) {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const uint_least8_t request[] = {
@@ -141,12 +143,11 @@
   return runCommand(request, writeStateTimeMs);
 }
 
-error_code
+Result<Ecc256::Signature::array>
 DS28C39::computeAndReadPageAuthentication(int pageNum, bool anonymous,
-                                          Page::const_span challenge,
-                                          Ecc256::Signature::span signature) {
+                                          Page::const_span challenge) const {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const size_t requestSize = 2 + Page::size;
@@ -155,63 +156,66 @@
   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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, requestSize), generateEcdsaSignatureTimeMs,
+                 make_span(buffer, responseSize));
+  if (!response) {
+    return response.error();
   }
-  return result;
+  Ecc256::Signature::array signature;
+  span<uint_least8_t>::const_iterator begin = response.value().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 signature;
 }
 
-error_code DS28C39::disableDevice() {
+Result<void> 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) {
+Result<Ecc256::PublicKey::array> DS28C39::readDevicePublicKey() const {
   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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, 1), generateEccKeyPairTimeMs, buffer);
+  if (!response) {
+    return response.error();
   }
-  return result;
+  Ecc256::PublicKey::array devicePublicKey;
+  span<uint_least8_t>::const_iterator begin = response.value().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 devicePublicKey;
 }
 
-error_code DS28C39::readRng(span<uint_least8_t> data) {
+Result<void> DS28C39::readRng(span<uint_least8_t> data) const {
   const span<uint_least8_t>::index_type maxDataSize = 64;
   if ((data.size() < 1) || (data.size() > maxDataSize)) {
-    return make_error_code(InvalidParameterError);
+    return 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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, 2), trngGenerationTimeMs,
+                 make_span(buffer, 1 + data.size()));
+  if (!response) {
+    return response.error();
   }
-  return result;
+  copy(response.value().begin(), response.value().end(), data.begin());
+  return none;
 }
 
-error_code
+Result<void>
 DS28C39::authenticatePublicKey(Ecc256::Signature::const_span certificate,
                                span<const uint_least8_t> customization) {
   static const span<const uint_least8_t>::index_type maxCustomizationSize = 32;
@@ -219,7 +223,7 @@
       2 * Ecc256::Scalar::size;
 
   if (customization.size() < 1 || customization.size() > maxCustomizationSize) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   uint_least8_t request[1 + signatureSize + maxCustomizationSize];
@@ -231,11 +235,11 @@
   return runCommand(make_span(request, requestIt), verifyEcdsaSignatureTimeMs);
 }
 
-error_code
+Result<void>
 DS28C39::authenticatedWriteMemory(int pageNum, Page::const_span page,
                                   Ecc256::Signature::const_span signature) {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   uint_least8_t request[2 + Page::size + 2 * Ecc256::Scalar::size];
@@ -248,43 +252,40 @@
   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;
+Result<span<uint_least8_t> >
+DS28C39::runCommand(span<const uint_least8_t> request, int delayTime,
+                    span<uint_least8_t> response) const {
+  const Result<span<uint_least8_t> > responseOutput =
+      doRunCommand(request, delayTime, response);
+  if (!responseOutput) {
+    return responseOutput;
   }
-  if (response.empty()) {
-    return make_error_code(InvalidResponseError);
+  if (responseOutput.value().empty()) {
+    return InvalidResponseError;
   }
   // Parse command result byte.
-  switch (response[0]) {
+  switch (responseOutput.value().front()) {
   case 0xAA:
     // Success response.
-    if (response.size() != responseInputSize) {
-      result = make_error_code(InvalidResponseError);
-    }
     break;
 
   case 0x00:
-    result = make_error_code(AuthenticationError);
-    break;
+    return AuthenticationError;
 
   default:
-    result.assign(response[0], errorCategory());
-    break;
+    return error_code(responseOutput.value().front(), errorCategory());
   }
-  response = response.subspan(1);
-  return result;
+  if (responseOutput.value().size() != response.size()) {
+    return InvalidResponseError;
+  }
+  return responseOutput.value().subspan(1);
 }
 
-error_code DS28C39::runCommand(span<const uint_least8_t> request,
-                               int delayTime) {
+Result<void> 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);
+  MaximInterfaceCore_TRY(runCommand(request, delayTime, make_span(&buffer, 1)));
+  return none;
 }
 
 const error_category & DS28C39::errorCategory() {
@@ -321,17 +322,6 @@
   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);
--- a/MaximInterfaceDevices/DS28C39.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS28C39.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceDevices_DS28C39
-#define MaximInterfaceDevices_DS28C39
+#ifndef MaximInterfaceDevices_DS28C39_hpp
+#define MaximInterfaceDevices_DS28C39_hpp
 
 #include <stdint.h>
 #include <MaximInterfaceCore/Algorithm.hpp>
@@ -96,13 +96,15 @@
       EntropyNotHealthy = 0xDD
     };
 
-    typedef Core::array<PageProtection, memoryPages - 2> PageProtectionList;
-    typedef Core::array<uint_least8_t, 2> RomVersion;
+    typedef Core::array_span<PageProtection, memoryPages - 2>
+        PageProtectionList;
 
-    PageProtectionList pageProtection;
+    typedef Core::array_span<uint_least8_t, 2> RomVersion;
+
+    PageProtectionList::array pageProtection;
     Core::RomId::array romId;
     Core::ManId::array manId;
-    RomVersion romVersion;
+    RomVersion::array romVersion;
     EntropyHealthTestStatus entropyHealthTestStatus;
   };
 
@@ -116,51 +118,50 @@
   /// @brief Write memory with no protection.
   /// @param pageNum Number of page to write.
   /// @param page Data to write.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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);
+  /// @returns Data that was read.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array>
+  readMemory(int pageNum) const;
 
   /// @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);
+  /// @returns Status that was read.
+  MaximInterfaceDevices_EXPORT Core::Result<Status>
+  readStatus(bool entropyHealthTest) const;
 
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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
+  /// @returns Computed page signature.
+  MaximInterfaceDevices_EXPORT Core::Result<Core::Ecc256::Signature::array>
   computeAndReadPageAuthentication(int pageNum, bool anonymous,
-                                   Page::const_span challenge,
-                                   Core::Ecc256::Signature::span signature);
+                                   Page::const_span challenge) const;
 
   /// Permanently disable the device.
-  MaximInterfaceDevices_EXPORT Core::error_code disableDevice();
+  MaximInterfaceDevices_EXPORT Core::Result<void> 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);
+  /// @returns Device Public Key
+  MaximInterfaceDevices_EXPORT Core::Result<Core::Ecc256::PublicKey::array>
+  readDevicePublicKey() const;
 
   /// @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 Core::Result<void>
+  readRng(Core::span<uint_least8_t> data) const;
 
   /// @brief
   /// Authenticate a public key for authenticated writes using the
@@ -169,7 +170,7 @@
   /// 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   authenticatePublicKey(Core::Ecc256::Signature::const_span certificate,
                         Core::span<const uint_least8_t> customization);
 
@@ -177,7 +178,7 @@
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   authenticatedWriteMemory(int pageNum, Page::const_span page,
                            Core::Ecc256::Signature::const_span signature);
 
@@ -185,29 +186,31 @@
   errorCategory();
 
 protected:
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<Core::span<uint_least8_t> >
   runCommand(Core::span<const uint_least8_t> request, int delayTime,
-             Core::span<uint_least8_t> & response);
+             Core::span<uint_least8_t> response) const;
 
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   runCommand(Core::span<const uint_least8_t> request, int delayTime);
 
 private:
   Core::RunCommand doRunCommand;
 };
 
+} // namespace MaximInterfaceDevices
+namespace MaximInterfaceCore {
+
+template <>
+struct is_error_code_enum<MaximInterfaceDevices::DS28C39::ErrorValue>
+    : true_type {};
+
+} // namespace MaximInterfaceCore
+namespace MaximInterfaceDevices {
+
 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:
@@ -327,13 +330,11 @@
   /// @}
 
 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;
+  static const size_t romIdIdx = 0;
+  static const size_t pageIdx = romIdIdx + Core::RomId::size;
+  static const size_t challengeIdx = pageIdx + Page::size;
+  static const size_t pageNumIdx = challengeIdx + Page::size;
+  static const size_t manIdIdx = pageNumIdx + 1;
 
   Result::array result_;
 };
--- a/MaximInterfaceDevices/DS28C40.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS28C40.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2019 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -39,6 +39,7 @@
 
 using namespace Core;
 using std::copy;
+using std::pair;
 
 static const int readMemoryTimeMs = 2;
 static const int writeMemoryTimeMs = 150;
@@ -73,9 +74,9 @@
 const int DS28C40::memoryPages;
 const int DS28C40::protectionBlocks;
 
-error_code DS28C40::writeMemory(int pageNum, Page::const_span page) {
+Result<void> DS28C40::writeMemory(int pageNum, Page::const_span page) {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   uint_least8_t request[2 + Page::size];
@@ -85,29 +86,28 @@
   return runCommand(request, writeMemoryTimeMs);
 }
 
-error_code DS28C40::readMemory(int pageNum, Page::span page) {
+Result<DS28C40::Page::array> DS28C40::readMemory(int pageNum) const {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return 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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, 2), readMemoryTimeMs, buffer);
+  if (!response) {
+    return response.error();
   }
-  return result;
+  Page::array page;
+  copy(response.value().begin(), response.value().end(), page.begin());
+  return page;
 }
 
-error_code
-DS28C40::encryptedReadMemory(int pageNum, KeySecret secret,
-                             EncryptionChallenge::span encryptionChallenge,
-                             Page::span encryptedPage) {
+Result<pair<DS28C40::EncryptionChallenge::array, DS28C40::Page::array> >
+DS28C40::encryptedReadMemory(int pageNum, KeySecret secret) const {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const size_t requestSize = 3;
@@ -116,27 +116,26 @@
   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());
+  const Result<span<uint_least8_t> > response = runCommand(
+      make_span(buffer, requestSize), readMemoryTimeMs + computeTimeMs,
+      make_span(buffer, responseSize));
+  if (!response) {
+    return response.error();
   }
-  return result;
+  pair<EncryptionChallenge::array, Page::array> data;
+  span<uint_least8_t>::const_iterator begin = response.value().begin();
+  span<uint_least8_t>::const_iterator end = begin + data.first.size();
+  copy(begin, end, data.first.begin());
+  begin = end;
+  end = begin + data.second.size();
+  copy(begin, end, data.second.begin());
+  return data;
 }
 
-error_code DS28C40::readBlockProtection(int blockNumber,
-                                        Optional<KeySecret> & keySecret,
-                                        BlockProtection & protection) {
+Result<pair<Optional<DS28C40::KeySecret>, DS28C40::BlockProtection> >
+DS28C40::readBlockProtection(int blockNumber) const {
   if (blockNumber < 0 || blockNumber >= protectionBlocks) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const size_t requestSize = 2;
@@ -144,39 +143,40 @@
   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;
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, requestSize), readMemoryTimeMs,
+                 make_span(buffer, responseSize));
+  if (!response) {
+    return response.error();
   }
-  if ((response[0] & 0x3F) != blockNumber) {
-    return make_error_code(InvalidResponseError);
+  if ((response.value()[0] & 0x3F) != blockNumber) {
+    return InvalidResponseError;
   }
-  switch (response[0] >> 6) {
+  pair<Optional<KeySecret>, BlockProtection> data;
+  switch (response.value()[0] >> 6) {
   case 0:
-    keySecret = none;
+    data.first = none;
     break;
   case 1:
-    keySecret = KeySecretA;
+    data.first = KeySecretA;
     break;
   case 2:
-    keySecret = KeySecretB;
+    data.first = KeySecretB;
     break;
   default:
-    return make_error_code(InvalidResponseError);
+    return InvalidResponseError;
   }
-  if ((response[1] & 0x20) != 0) {
-    return make_error_code(InvalidResponseError);
+  if ((response.value()[1] & 0x20) != 0) {
+    return InvalidResponseError;
   }
-  protection = response[1];
-  return error_code();
+  data.second = response.value()[1];
+  return data;
 }
 
-error_code DS28C40::setBlockProtection(int blockNum, KeySecret keySecret,
-                                       const BlockProtection & protection) {
+Result<void> DS28C40::setBlockProtection(int blockNum, KeySecret keySecret,
+                                         const BlockProtection & protection) {
   if (blockNum < 0 || blockNum >= protectionBlocks || keySecret == KeySecretS) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const uint_least8_t request[] = {
@@ -187,12 +187,10 @@
   return runCommand(request, writeStateTimeMs);
 }
 
-error_code
-DS28C40::computeAndReadPageAuthentication(int pageNum, KeySecret key,
-                                          Page::const_span challenge,
-                                          Ecc256::Signature::span signature) {
+Result<Ecc256::Signature::array> DS28C40::computeAndReadEcdsaPageAuthentication(
+    int pageNum, KeySecret key, Page::const_span challenge) const {
   if (pageNum < 0 || pageNum >= memoryPages || key == KeySecretS) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const size_t requestSize = 3 + Page::size;
@@ -202,26 +200,26 @@
   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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, requestSize), generateEcdsaSignatureTimeMs,
+                 make_span(buffer, responseSize));
+  if (!response) {
+    return response.error();
   }
-  return result;
+  Ecc256::Signature::array signature;
+  span<uint_least8_t>::const_iterator begin = response.value().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 signature;
 }
 
-error_code DS28C40::computeAndReadPageAuthentication(int pageNum,
-                                                     KeySecret secret,
-                                                     Page::const_span challenge,
-                                                     Page::span hmac) {
+Result<DS28C40::Page::array> DS28C40::computeAndReadSha256PageAuthentication(
+    int pageNum, KeySecret secret, Page::const_span challenge) const {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const size_t requestSize = 3 + Page::size;
@@ -231,21 +229,23 @@
   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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, requestSize), computeTimeMs,
+                 make_span(buffer, responseSize));
+  if (!response) {
+    return response.error();
   }
-  return result;
+  Page::array hmac;
+  copy(response.value().begin(), response.value().end(), hmac.begin());
+  return hmac;
 }
 
-error_code DS28C40::computeMultiblockHash(bool firstBlock, bool lastBlock,
-                                          span<const uint_least8_t> data) {
+Result<void> 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);
+    return InvalidParameterError;
   }
 
   uint_least8_t buffer[2 + maxDataSize];
@@ -261,21 +261,21 @@
   return runCommand(make_span(buffer, 2 + data.size()), computeTimeMs);
 }
 
-error_code DS28C40::verifyEcdsaSignature(
+Result<void> 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(
+Result<void> 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
+Result<void>
 DS28C40::verifyEcdsaSignature(KeySecret key, bool authorityKey,
                               GpioState gpioState,
                               Ecc256::Signature::const_span signature) {
@@ -283,13 +283,13 @@
                               span<const uint_least8_t>());
 }
 
-error_code DS28C40::verifyEcdsaSignature(
+Result<void> 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);
+    return InvalidParameterError;
   }
 
   uint_least8_t request[2 + 2 * Ecc256::Scalar::size + maxBufferSize];
@@ -317,7 +317,7 @@
     }
     // else: Go to default case.
   default:
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
   *requestIt |= hashType << 3;
   if (gpioState != Unchanged) {
@@ -334,13 +334,13 @@
                         (hashType == DataInput ? computeTimeMs : 0));
 }
 
-error_code DS28C40::authenticateEcdsaPublicKey(
+Result<void> 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(
+Result<void> DS28C40::authenticateEcdsaPublicKey(
     KeySecret key, bool authWrites, Ecc256::Signature::const_span cert,
     span<const uint_least8_t> certCustomization,
     span<const uint_least8_t> ecdhCustomization) {
@@ -348,7 +348,7 @@
                                     &ecdhCustomization);
 }
 
-error_code DS28C40::authenticateEcdsaPublicKey(
+Result<void> DS28C40::authenticateEcdsaPublicKey(
     KeySecret key, bool authWrites, Ecc256::Signature::const_span cert,
     span<const uint_least8_t> certCustomization,
     const span<const uint_least8_t> * ecdhCustomization) {
@@ -364,11 +364,11 @@
           ecdhCustomization->size() <= maxEcdhCustomizationSize &&
           certCustomization.size() + ecdhCustomization->size() <=
               maxTotalCustomizationSize)))) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   if (key == KeySecretS) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   uint_least8_t
@@ -395,14 +395,14 @@
   return runCommand(make_span(request, requestIt), delay);
 }
 
-error_code DS28C40::authenticatedEcdsaWriteMemory(
+Result<void> 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(
+Result<void> DS28C40::authenticatedEcdsaWriteMemory(
     int pageNum, bool useKeyS, Page::const_span newPageData,
     Ecc256::Signature::const_span signature,
     EncryptionChallenge::const_span challenge) {
@@ -410,12 +410,12 @@
                                        &challenge);
 }
 
-error_code DS28C40::authenticatedEcdsaWriteMemory(
+Result<void> 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);
+    return InvalidParameterError;
   }
 
   uint_least8_t request[2 + Page::size + 2 * Ecc256::Scalar::size +
@@ -437,25 +437,26 @@
   return runCommand(make_span(request, requestIt), delay);
 }
 
-error_code DS28C40::authenticatedSha256WriteMemory(int pageNum, bool useSecretS,
-                                                   Page::const_span newPageData,
-                                                   Page::const_span hmac) {
+Result<void>
+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(
+Result<void> 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(
+Result<void> 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);
+    return InvalidParameterError;
   }
 
   uint_least8_t request[3 + 2 * Page::size + EncryptionChallenge::size];
@@ -473,12 +474,12 @@
   return runCommand(make_span(request, requestIt), delay);
 }
 
-error_code
+Result<void>
 DS28C40::computeAndWriteSha256Secret(int pageNum, KeySecret masterSecret,
                                      KeySecret destinationSecret,
                                      Page::const_span partialSecret) {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   uint_least8_t request[3 + Page::size];
@@ -489,75 +490,73 @@
   return runCommand(request, writeMemoryTimeMs + computeTimeMs);
 }
 
-error_code DS28C40::generateEcc256KeyPair(KeySecret key) {
+Result<void> DS28C40::generateEcc256KeyPair(KeySecret key) {
   if (key == KeySecretS) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const uint_least8_t request[] = {0xCB, key == KeySecretB};
   return runCommand(request, generateEccKeyPairTimeMs);
 }
 
-error_code DS28C40::readRng(span<uint_least8_t> data) {
+Result<void> DS28C40::readRng(span<uint_least8_t> data) const {
   const span<uint_least8_t>::index_type maxDataSize = 64;
   if ((data.size() < 1) || (data.size() > maxDataSize)) {
-    return make_error_code(InvalidParameterError);
+    return 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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, 2), trngGenerationTimeMs,
+                 make_span(buffer, 1 + data.size()));
+  if (!response) {
+    return response.error();
   }
-  return result;
+  copy(response.value().begin(), response.value().end(), data.begin());
+  return none;
 }
 
-error_code DS28C40::entropyHealthTest() {
+Result<void> DS28C40::entropyHealthTest() const {
   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;
+Result<span<uint_least8_t> >
+DS28C40::runCommand(span<const uint_least8_t> request, int delayTime,
+                    span<uint_least8_t> response) const {
+  const Result<span<uint_least8_t> > responseOutput =
+      doRunCommand(request, delayTime, response);
+  if (!responseOutput) {
+    return responseOutput;
   }
-  if (response.empty()) {
-    return make_error_code(InvalidResponseError);
+  if (responseOutput.value().empty()) {
+    return InvalidResponseError;
   }
   // Parse command result byte.
-  switch (response[0]) {
+  switch (responseOutput.value().front()) {
   case 0xAA:
     // Success response.
-    if (response.size() != responseInputSize) {
-      result = make_error_code(InvalidResponseError);
-    }
     break;
 
   case 0x00:
-    result = make_error_code(AuthenticationError);
-    break;
+    return AuthenticationError;
 
   default:
-    result.assign(response[0], errorCategory());
-    break;
+    return error_code(responseOutput.value().front(), errorCategory());
   }
-  response = response.subspan(1);
-  return result;
+  if (responseOutput.value().size() != response.size()) {
+    return InvalidResponseError;
+  }
+  return responseOutput.value().subspan(1);
 }
 
-error_code DS28C40::runCommand(span<const uint_least8_t> request,
-                               int delayTime) {
+Result<void> DS28C40::runCommand(span<const uint_least8_t> request,
+                                 int delayTime) const {
   uint_least8_t buffer;
-  span<uint_least8_t> response(&buffer, 1);
-  return runCommand(request, delayTime, response);
+  MaximInterfaceCore_TRY(runCommand(request, delayTime, make_span(&buffer, 1)));
+  return none;
 }
 
 const error_category & DS28C40::errorCategory() {
@@ -594,33 +593,20 @@
   return instance;
 }
 
-error_code computeMultiblockHash(DS28C40 & device,
-                                 span<const uint_least8_t> data) {
-  error_code result;
+Result<void> computeMultiblockHash(DS28C40 & device,
+                                   span<const uint_least8_t> data) {
   span<const uint_least8_t>::index_type dataIdx = 0;
-  while (dataIdx < data.size() && !result) {
+  while (dataIdx < data.size()) {
     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 =
+    MaximInterfaceCore_TRY(
         device.computeMultiblockHash(dataIdx == 0, remainingSize == chunkSize,
-                                     data.subspan(dataIdx, 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;
+  return none;
 }
 
 static void setAnonymous(RomId::span romId) {
--- a/MaximInterfaceDevices/DS28C40.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS28C40.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2019 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,10 +30,11 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceDevices_DS28C40
-#define MaximInterfaceDevices_DS28C40
+#ifndef MaximInterfaceDevices_DS28C40_hpp
+#define MaximInterfaceDevices_DS28C40_hpp
 
 #include <stdint.h>
+#include <utility>
 #include <MaximInterfaceCore/Algorithm.hpp>
 #include <MaximInterfaceCore/array_span.hpp>
 #include <MaximInterfaceCore/Ecc256.hpp>
@@ -140,38 +141,35 @@
   /// @brief Write memory with no protection.
   /// @param pageNum Number of page to write.
   /// @param page Data to write.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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);
+  /// @returns Data that was read.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array>
+  readMemory(int pageNum) const;
 
   /// @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);
+  /// @returns Encryption challenge and encrypted page data that was read.
+  MaximInterfaceDevices_EXPORT
+      Core::Result<std::pair<EncryptionChallenge::array, Page::array> >
+      encryptedReadMemory(int pageNum, KeySecret secret) const;
 
   /// @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);
+  /// @returns Secret/Key and protection set on the block.
+  MaximInterfaceDevices_EXPORT
+      Core::Result<std::pair<Core::Optional<KeySecret>, BlockProtection> >
+      readBlockProtection(int blockNum) const;
 
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   setBlockProtection(int blockNum, KeySecret keySecret,
                      const BlockProtection & protection);
 
@@ -181,11 +179,10 @@
   /// 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);
+  /// @returns Computed page signature.
+  MaximInterfaceDevices_EXPORT Core::Result<Core::Ecc256::Signature::array>
+  computeAndReadEcdsaPageAuthentication(int pageNum, KeySecret key,
+                                        Page::const_span challenge) const;
 
   /// @brief Compute and read page authentication with HMAC.
   /// @param pageNum Number of page to authenticate.
@@ -193,17 +190,17 @@
   /// 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);
+  /// @returns Computed page HMAC.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array>
+  computeAndReadSha256PageAuthentication(int pageNum, KeySecret secret,
+                                         Page::const_span challenge) const;
 
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   computeMultiblockHash(bool firstBlock, bool lastBlock,
                         Core::span<const uint_least8_t> data);
 
@@ -213,7 +210,7 @@
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState,
                        Core::Ecc256::Signature::const_span signature,
                        Core::span<const uint_least8_t> data);
@@ -224,7 +221,7 @@
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState,
                        Core::Ecc256::Signature::const_span signature,
                        Page::const_span hash);
@@ -235,7 +232,7 @@
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState,
                        Core::Ecc256::Signature::const_span signature);
 
@@ -245,7 +242,7 @@
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   authenticateEcdsaPublicKey(KeySecret key,
                              Core::Ecc256::Signature::const_span cert,
                              Core::span<const uint_least8_t> certCustomization);
@@ -261,7 +258,7 @@
   /// 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   authenticateEcdsaPublicKey(KeySecret key, bool authWrites,
                              Core::Ecc256::Signature::const_span cert,
                              Core::span<const uint_least8_t> certCustomization,
@@ -273,7 +270,7 @@
   /// 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   authenticatedEcdsaWriteMemory(int pageNum, bool useKeyS,
                                 Page::const_span newPageData,
                                 Core::Ecc256::Signature::const_span signature);
@@ -285,7 +282,7 @@
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   authenticatedEcdsaWriteMemory(int pageNum, bool useKeyS,
                                 Page::const_span newPageData,
                                 Core::Ecc256::Signature::const_span signature,
@@ -297,7 +294,7 @@
   /// 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   authenticatedSha256WriteMemory(int pageNum, bool useSecretS,
                                  Page::const_span newPageData,
                                  Page::const_span hmac);
@@ -309,9 +306,11 @@
   /// @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);
+  MaximInterfaceDevices_EXPORT Core::Result<void>
+  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.
@@ -319,23 +318,23 @@
   /// @param destinationSecret
   /// Destination secret to receive the computation result.
   /// @param partialSecret Partial secret to use in computation.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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);
+  MaximInterfaceDevices_EXPORT Core::Result<void>
+  readRng(Core::span<uint_least8_t> data) const;
 
   /// Run entropy health test on the RNG.
-  MaximInterfaceDevices_EXPORT Core::error_code entropyHealthTest();
+  MaximInterfaceDevices_EXPORT Core::Result<void> entropyHealthTest() const;
 
   MaximInterfaceDevices_EXPORT static const Core::error_category &
   errorCategory();
@@ -343,36 +342,46 @@
 private:
   enum HashType { HashInput, DataInput, THASH };
 
-  Core::error_code
+  Core::Result<void>
   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(
+  Core::Result<void> 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(
+  Core::Result<void> authenticatedEcdsaWriteMemory(
       int pageNum, bool useKeyS, Page::const_span newPageData,
       Core::Ecc256::Signature::const_span signature,
       const EncryptionChallenge::const_span * challenge);
 
-  Core::error_code authenticatedSha256WriteMemory(
+  Core::Result<void> 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::Result<Core::span<uint_least8_t> >
+  runCommand(Core::span<const uint_least8_t> request, int delayTime,
+             Core::span<uint_least8_t> response) const;
 
-  Core::error_code runCommand(Core::span<const uint_least8_t> request,
-                              int delayTime);
+  Core::Result<void> runCommand(Core::span<const uint_least8_t> request,
+                                int delayTime) const;
 
   Core::RunCommand doRunCommand;
 };
 
+} // namespace MaximInterfaceDevices
+namespace MaximInterfaceCore {
+
+template <>
+struct is_error_code_enum<MaximInterfaceDevices::DS28C40::ErrorValue>
+    : true_type {};
+
+} // namespace MaximInterfaceCore
+namespace MaximInterfaceDevices {
+
 inline Core::error_code make_error_code(DS28C40::ErrorValue e) {
   return Core::error_code(e, DS28C40::errorCategory());
 }
@@ -381,19 +390,9 @@
 /// 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
+MaximInterfaceDevices_EXPORT Core::Result<void>
 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:
@@ -513,13 +512,11 @@
   /// @}
 
 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;
+  static const size_t romIdIdx = 0;
+  static const size_t pageIdx = romIdIdx + Core::RomId::size;
+  static const size_t challengeIdx = pageIdx + Page::size;
+  static const size_t pageNumIdx = challengeIdx + Page::size;
+  static const size_t manIdIdx = pageNumIdx + 1;
 
   Result::array result_;
 };
@@ -827,13 +824,11 @@
   /// @}
 
 private:
-  typedef Result::span::index_type index;
-
-  static const index encryptionChallengeIdx = 0;
-  static const index romIdIdx =
+  static const size_t encryptionChallengeIdx = 0;
+  static const size_t romIdIdx =
       encryptionChallengeIdx + EncryptionChallenge::size;
-  static const index pageNumIdx = romIdIdx + Core::RomId::size;
-  static const index manIdIdx = pageNumIdx + 1;
+  static const size_t pageNumIdx = romIdIdx + Core::RomId::size;
+  static const size_t manIdIdx = pageNumIdx + 1;
 
   Result::array result_;
 };
--- a/MaximInterfaceDevices/DS28E15_22_25.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS28E15_22_25.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -31,10 +31,13 @@
 *******************************************************************************/
 
 #include <algorithm>
-#include <MaximInterfaceCore/crc.hpp>
+#include <MaximInterfaceCore/Crc.hpp>
 #include <MaximInterfaceCore/Error.hpp>
 #include "DS28E15_22_25.hpp"
 
+#define TRY MaximInterfaceCore_TRY
+#define TRY_VALUE MaximInterfaceCore_TRY_VALUE
+
 namespace MaximInterfaceDevices {
 
 using namespace Core;
@@ -48,27 +51,18 @@
 
 static const int ds28e22_25_pagesPerBlock = 2;
 
-static error_code
+static Result<void>
 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;
-  }
+  TRY(master.writeBlock(data));
   uint_least8_t response[2];
-  result = master.readByte(response[0]);
-  if (result) {
-    return result;
+  TRY_VALUE(response[0], master.readByte());
+  TRY_VALUE(response[1], master.readByteSetLevel(level));
+  if (calculateCrc16(calculateCrc16(crcStart, data), response) != 0xB001u) {
+    return DS28E15_22_25::CrcError;
   }
-  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;
+  return none;
 }
 
 const int DS28E15_22_25::segmentsPerPage;
@@ -79,11 +73,11 @@
   return *this;
 }
 
-error_code
+Result<void>
 DS28E15_22_25::writeCommandWithCrc(Command command, uint_least8_t parameter,
                                    OneWireMaster::Level level) const {
-  error_code result = selectRom(*master);
-  if (!result) {
+  Result<void> result = selectRom(*master);
+  if (result) {
     const uint_least8_t data[] = {static_cast<uint_least8_t>(command),
                                   parameter};
     result = writeDataWithCrc(*master, data, level);
@@ -91,44 +85,41 @@
   return result;
 }
 
-static error_code readDataWithCrc(OneWireMaster & master,
-                                  span<uint_least8_t> data) {
-  error_code result = master.readBlock(data);
-  if (result) {
+static Result<void> readDataWithCrc(OneWireMaster & master,
+                                    span<uint_least8_t> data) {
+  Result<void> result = master.readBlock(data);
+  if (!result) {
     return result;
   }
   uint_least8_t response[2];
   result = master.readBlock(response);
-  if (result) {
+  if (!result) {
     return result;
   }
-  if (calculateCrc16(calculateCrc16(data), response) != 0xB001) {
-    result = make_error_code(DS28E15_22_25::CrcError);
+  if (calculateCrc16(calculateCrc16(data), response) != 0xB001u) {
+    result = 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;
+static Result<void> readCsByte(OneWireMaster & master) {
+  const Result<uint_least8_t> response = master.readByte();
+  if (!response) {
+    return response.error();
   }
-  if (response != 0xAA) {
-    result = make_error_code(DS28E15_22_25::OperationFailure);
-  }
-  return result;
+  return (response.value() == 0xAA) ? makeResult(none)
+                                    : DS28E15_22_25::OperationFailure;
 }
 
-static error_code releaseSequence(OneWireMaster & master, Sleep & sleep,
-                                  int delayTimeMs) {
-  error_code result = master.writeBytePower(0xAA);
-  if (result) {
+static Result<void> releaseSequence(OneWireMaster & master, Sleep & sleep,
+                                    int delayTimeMs) {
+  Result<void> result = master.writeBytePower(0xAA);
+  if (!result) {
     return result;
   }
   sleep(delayTimeMs);
   result = master.setLevel(OneWireMaster::NormalLevel);
-  if (result) {
+  if (!result) {
     return result;
   }
   return readCsByte(master);
@@ -215,29 +206,29 @@
   return *this;
 }
 
-error_code
+Result<void>
 DS28E15_22_25::writeAuthBlockProtection(BlockProtection newProtection,
                                         Page::const_span mac) {
-  error_code result =
+  Result<void> result =
       writeCommandWithCrc(AuthWriteBlockProtection, newProtection.statusByte(),
                           OneWireMaster::StrongLevel);
-  if (result) {
+  if (!result) {
     return result;
   }
 
   sleep->invoke(shaComputationDelayMs);
   result = master->setLevel(OneWireMaster::NormalLevel);
-  if (result) {
+  if (!result) {
     return result;
   }
 
   result = writeDataWithCrc(*master, mac);
-  if (result) {
+  if (!result) {
     return result;
   }
 
   result = readCsByte(*master);
-  if (result) {
+  if (!result) {
     return result;
   }
 
@@ -245,10 +236,10 @@
   return result;
 }
 
-error_code DS28E15_22_25::writeBlockProtection(BlockProtection protection) {
-  error_code result =
+Result<void> DS28E15_22_25::writeBlockProtection(BlockProtection protection) {
+  Result<void> result =
       writeCommandWithCrc(WriteBlockProtection, protection.statusByte());
-  if (result) {
+  if (!result) {
     return result;
   }
 
@@ -256,52 +247,51 @@
   return result;
 }
 
-error_code DS28E15_22_25::doReadBlockProtection(int blockNum,
-                                                BlockProtection & protection,
-                                                Variant variant) const {
+Result<DS28E15_22_25::BlockProtection>
+DS28E15_22_25::doReadBlockProtection(int blockNum, 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;
+  TRY(writeCommandWithCrc(ReadStatus, buffer));
+  TRY_VALUE(buffer, master->readByte());
+  return BlockProtection(buffer);
 }
 
-error_code DS28E15_22_25::computeReadPageMac(int page_num, bool anon,
-                                             Page::span mac) const {
-  error_code result =
+Result<DS28E15_22_25::Page::array>
+DS28E15_22_25::computeReadPageMac(int page_num, bool anon) const {
+  Result<void> result =
       writeCommandWithCrc(ComputePageMac, (anon ? 0xE0 : 0x00) | page_num,
                           OneWireMaster::StrongLevel);
-  if (result) {
-    return result;
+  if (!result) {
+    return result.error();
   }
 
   sleep->invoke(shaComputationDelayMs * 2);
   result = master->setLevel(OneWireMaster::NormalLevel);
-  if (result) {
-    return result;
+  if (!result) {
+    return result.error();
   }
 
   result = readCsByte(*master);
-  if (result) {
-    return result;
+  if (!result) {
+    return result.error();
   }
 
+  Page::array mac;
   result = readDataWithCrc(*master, mac);
-  return result;
+  if (!result) {
+    return result.error();
+  }
+
+  return mac;
 }
 
-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) {
+Result<void> DS28E15_22_25::doComputeSecret(int page_num, bool lock,
+                                            bool lowPower) {
+  Result<void> result = writeCommandWithCrc(
+      ComputeAndLockSecret, lock ? (0xE0 | page_num) : page_num);
+  if (!result) {
     return result;
   }
 
@@ -311,12 +301,12 @@
   return result;
 }
 
-error_code DS28E15_22_25::doWriteScratchpad(Page::const_span data,
-                                            Variant variant) {
+Result<void> 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) {
+  Result<void> result = writeCommandWithCrc(ReadWriteScratchpad, parameter);
+  if (!result) {
     return result;
   }
 
@@ -324,23 +314,28 @@
   return result;
 }
 
-error_code DS28E15_22_25::doReadScratchpad(Page::span data,
-                                           Variant variant) const {
+Result<DS28E15_22_25::Page::array>
+DS28E15_22_25::doReadScratchpad(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<void> result = writeCommandWithCrc(ReadWriteScratchpad, parameter);
+  if (!result) {
+    return result.error();
   }
 
+  Page::array data;
   result = readDataWithCrc(*master, data);
-  return result;
+  if (!result) {
+    return result.error();
+  }
+
+  return data;
 }
 
-error_code DS28E15_22_25::doLoadSecret(bool lock, bool lowPower) {
-  error_code result =
+Result<void> DS28E15_22_25::doLoadSecret(bool lock, bool lowPower) {
+  Result<void> result =
       writeCommandWithCrc(LoadAndLockSecret, lock ? 0xE0 : 0x00);
-  if (result) {
+  if (!result) {
     return result;
   }
 
@@ -348,47 +343,49 @@
   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<DS28E15_22_25::Page::array> DS28E15_22_25::readPage(int page) const {
+  const Result<void> result = writeCommandWithCrc(ReadMemory, page);
+  if (!result) {
+    return result.error();
   }
 
-  result = continueReadPage(rdbuf);
-  return result;
+  return continueReadPage();
 }
 
-error_code DS28E15_22_25::continueReadPage(Page::span rdbuf) const {
-  return readDataWithCrc(*master, rdbuf);
+Result<DS28E15_22_25::Page::array> DS28E15_22_25::continueReadPage() const {
+  Page::array rdbuf;
+  TRY(readDataWithCrc(*master, rdbuf));
+  return rdbuf;
 }
 
-error_code DS28E15_22_25::doWriteAuthSegment(Segment::const_span newData,
-                                             Page::const_span mac,
-                                             Variant variant, bool continuing) {
+Result<void> 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 =
+  Result<void> result =
       writeDataWithCrc(*master, newData, OneWireMaster::StrongLevel, crcStart);
-  if (result) {
+  if (!result) {
     return result;
   }
 
   sleep->invoke(shaComputationDelayMs);
   result = master->setLevel(OneWireMaster::NormalLevel);
-  if (result) {
+  if (!result) {
     return result;
   }
 
   result = writeDataWithCrc(*master, mac);
-  if (result) {
+  if (!result) {
     return result;
   }
 
   result = readCsByte(*master);
-  if (result) {
+  if (!result) {
     return result;
   }
 
@@ -396,13 +393,13 @@
   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 =
+Result<void> DS28E15_22_25::doWriteAuthSegment(int pageNum, int segmentNum,
+                                               Segment::const_span newData,
+                                               Page::const_span mac,
+                                               Variant variant) {
+  Result<void> result =
       writeCommandWithCrc(AuthWriteMemory, (segmentNum << 5) | pageNum);
-  if (result) {
+  if (!result) {
     return result;
   }
 
@@ -410,30 +407,32 @@
   return result;
 }
 
-error_code DS28E15_22_25::doContinueWriteAuthSegment(
+Result<void> 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<DS28E15_22_25::Segment::array>
+DS28E15_22_25::readSegment(int page, int segment) const {
+  Result<void> result = writeCommandWithCrc(ReadMemory, (segment << 5) | page);
+  if (!result) {
+    return result.error();
   }
 
-  result = continueReadSegment(data);
-  return result;
+  return continueReadSegment();
 }
 
-error_code DS28E15_22_25::continueReadSegment(Segment::span data) const {
-  return master->readBlock(data);
+Result<DS28E15_22_25::Segment::array>
+DS28E15_22_25::continueReadSegment() const {
+  Segment::array data;
+  TRY(master->readBlock(data));
+  return 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) {
+Result<void> DS28E15_22_25::writeSegment(int page, int block,
+                                         Segment::const_span data) {
+  Result<void> result = writeCommandWithCrc(WriteMemory, (block << 5) | page);
+  if (!result) {
     return result;
   }
 
@@ -441,9 +440,9 @@
   return result;
 }
 
-error_code DS28E15_22_25::continueWriteSegment(Segment::const_span data) {
-  error_code result = writeDataWithCrc(*master, data);
-  if (result) {
+Result<void> DS28E15_22_25::continueWriteSegment(Segment::const_span data) {
+  Result<void> result = writeDataWithCrc(*master, data);
+  if (!result) {
     return result;
   }
 
@@ -451,10 +450,10 @@
   return result;
 }
 
-error_code
+Result<void>
 DS28E15_22_25::doReadAllBlockProtection(span<BlockProtection> protection,
                                         Variant variant) const {
-  error_code result = writeCommandWithCrc(ReadStatus, 0);
+  Result<void> result = writeCommandWithCrc(ReadStatus, 0);
   if (!result) {
     if (variant == DS28E22 || variant == DS28E25) {
       // Need to read extra data on DS28E22 to get CRC16.
@@ -502,151 +501,166 @@
 
       case OperationFailure:
         return "Operation Failure";
-
-      default:
-        return defaultErrorMessage(condition);
       }
+      return defaultErrorMessage(condition);
     }
   } instance;
   return instance;
 }
 
-error_code DS28E15_22_25::loadSecret(bool lock) {
+Result<void> 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) {
+Result<void> 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);
+Result<DS28E15_22_25::Personality> DS28E15_22_25::readPersonality() const {
+  Result<void> result = writeCommandWithCrc(ReadStatus, 0xE0);
+  if (!result) {
+    return result.error();
+  }
+
+  uint_least8_t data[4];
+  result = readDataWithCrc(*master, data);
   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.error();
   }
-  return result;
+
+  Personality personality;
+  personality.PB1 = data[0];
+  personality.PB2 = data[1];
+  personality.manId[0] = data[2];
+  personality.manId[1] = data[3];
+  return personality;
 }
 
 const int DS28EL15::memoryPages;
 const int DS28EL15::protectionBlocks;
 
-error_code DS28EL15::writeScratchpad(Page::const_span data) {
+Result<void> DS28EL15::writeScratchpad(Page::const_span data) {
   return doWriteScratchpad(data, DS28E15);
 }
 
-error_code DS28EL15::readScratchpad(Page::span data) const {
-  return doReadScratchpad(data, DS28E15);
+Result<DS28E15_22_25::Page::array> DS28EL15::readScratchpad() const {
+  return doReadScratchpad(DS28E15);
 }
 
-error_code DS28EL15::readBlockProtection(int blockNum,
-                                         BlockProtection & protection) const {
-  return doReadBlockProtection(blockNum, protection, DS28E15);
+Result<DS28E15_22_25::BlockProtection>
+DS28EL15::readBlockProtection(int blockNum) const {
+  return doReadBlockProtection(blockNum, DS28E15);
 }
 
-error_code DS28EL15::writeAuthSegment(int pageNum, int segmentNum,
-                                      Segment::const_span newData,
-                                      Page::const_span mac) {
+Result<void> 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) {
+Result<void> 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);
+Result<array<DS28E15_22_25::BlockProtection, DS28E15::protectionBlocks> >
+DS28EL15::readAllBlockProtection() const {
+  array<BlockProtection, protectionBlocks> protection;
+  TRY(doReadAllBlockProtection(protection, DS28E15));
+  return protection;
 }
 
-error_code DS28E15::loadSecret(bool lock) { return doLoadSecret(lock, false); }
+Result<void> DS28E15::loadSecret(bool lock) {
+  return doLoadSecret(lock, false);
+}
 
-error_code DS28E15::computeSecret(int pageNum, bool lock) {
+Result<void> 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) {
+Result<void> DS28EL22::writeScratchpad(Page::const_span data) {
   return doWriteScratchpad(data, DS28E22);
 }
 
-error_code DS28EL22::readScratchpad(Page::span data) const {
-  return doReadScratchpad(data, DS28E22);
+Result<DS28E15_22_25::Page::array> DS28EL22::readScratchpad() const {
+  return doReadScratchpad(DS28E22);
 }
 
-error_code DS28EL22::readBlockProtection(int blockNum,
-                                         BlockProtection & protection) const {
-  return doReadBlockProtection(blockNum, protection, DS28E22);
+Result<DS28E15_22_25::BlockProtection>
+DS28EL22::readBlockProtection(int blockNum) const {
+  return doReadBlockProtection(blockNum, DS28E22);
 }
 
-error_code DS28EL22::writeAuthSegment(int pageNum, int segmentNum,
-                                      Segment::const_span newData,
-                                      Page::const_span mac) {
+Result<void> 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) {
+Result<void> 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);
+Result<array<DS28E15_22_25::BlockProtection, DS28E22::protectionBlocks> >
+DS28EL22::readAllBlockProtection() const {
+  array<BlockProtection, protectionBlocks> protection;
+  TRY(doReadAllBlockProtection(protection, DS28E22));
+  return protection;
 }
 
-error_code DS28E22::loadSecret(bool lock) { return doLoadSecret(lock, false); }
+Result<void> DS28E22::loadSecret(bool lock) {
+  return doLoadSecret(lock, false);
+}
 
-error_code DS28E22::computeSecret(int pageNum, bool lock) {
+Result<void> 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) {
+Result<void> DS28EL25::writeScratchpad(Page::const_span data) {
   return doWriteScratchpad(data, DS28E25);
 }
 
-error_code DS28EL25::readScratchpad(Page::span data) const {
-  return doReadScratchpad(data, DS28E25);
+Result<DS28E15_22_25::Page::array> DS28EL25::readScratchpad() const {
+  return doReadScratchpad(DS28E25);
 }
 
-error_code DS28EL25::readBlockProtection(int blockNum,
-                                         BlockProtection & protection) const {
-  return doReadBlockProtection(blockNum, protection, DS28E25);
+Result<DS28E15_22_25::BlockProtection>
+DS28EL25::readBlockProtection(int blockNum) const {
+  return doReadBlockProtection(blockNum, DS28E25);
 }
 
-error_code DS28EL25::writeAuthSegment(int pageNum, int segmentNum,
-                                      Segment::const_span newData,
-                                      Page::const_span mac) {
+Result<void> 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) {
+Result<void> 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);
+Result<array<DS28E15_22_25::BlockProtection, DS28E25::protectionBlocks> >
+DS28EL25::readAllBlockProtection() const {
+  array<BlockProtection, protectionBlocks> protection;
+  TRY(doReadAllBlockProtection(protection, DS28E25));
+  return protection;
 }
 
-error_code DS28E25::loadSecret(bool lock) { return doLoadSecret(lock, false); }
+Result<void> DS28E25::loadSecret(bool lock) {
+  return doLoadSecret(lock, false);
+}
 
-error_code DS28E25::computeSecret(int pageNum, bool lock) {
+Result<void> DS28E25::computeSecret(int pageNum, bool lock) {
   return doComputeSecret(pageNum, lock, false);
 }
 
--- a/MaximInterfaceDevices/DS28E15_22_25.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS28E15_22_25.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceDevices_DS28E15_22_25
-#define MaximInterfaceDevices_DS28E15_22_25
+#ifndef MaximInterfaceDevices_DS28E15_22_25_hpp
+#define MaximInterfaceDevices_DS28E15_22_25_hpp
 
 #include <stdint.h>
 #include <MaximInterfaceCore/Algorithm.hpp>
@@ -48,6 +48,9 @@
 /// @brief
 /// Interface to the DS28E15/22/25 series of authenticators
 /// including low power variants.
+/// @details
+/// Const member functions should not affect the state of the memory,
+/// block protection, or secret on the device.
 class DS28E15_22_25 {
 public:
   enum ErrorValue { CrcError = 1, OperationFailure };
@@ -91,54 +94,51 @@
     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;
+  /// @returns Buffer to read data from the segment into.
+  MaximInterfaceDevices_EXPORT Core::Result<Segment::array>
+  readSegment(int pageNum, int segmentNum) 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;
+  /// @returns Buffer to read data from the segment into.
+  MaximInterfaceDevices_EXPORT Core::Result<Segment::array>
+  continueReadSegment() 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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;
+  /// @returns Buffer to read data from the page into.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array>
+  readPage(int pageNum) 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;
+  /// @returns Buffer to read data from the page into.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array>
+  continueReadPage() 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;
+  /// @returns The device computed MAC.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array>
+  computeReadPageMac(int pageNum, bool anon) const;
 
   /// @brief
   /// Update the status of a memory protection block using the
@@ -146,7 +146,7 @@
   /// @param protection
   /// Desired protection status for the block.
   /// It is not possible to disable existing protections.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   writeBlockProtection(BlockProtection protection);
 
   /// @brief
@@ -154,26 +154,26 @@
   /// 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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);
+  MaximInterfaceDevices_EXPORT Core::Result<void> 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);
+  MaximInterfaceDevices_EXPORT Core::Result<void> 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;
+  /// @returns Receives personality read from device.
+  MaximInterfaceDevices_EXPORT Core::Result<Personality>
+  readPersonality() const;
 
   MaximInterfaceDevices_EXPORT static const Core::error_category &
   errorCategory();
@@ -187,29 +187,28 @@
 
   ~DS28E15_22_25() {}
 
-  Core::error_code doWriteScratchpad(Page::const_span data, Variant variant);
-
-  Core::error_code doReadScratchpad(Page::span data, Variant variant) const;
+  Core::Result<void> doWriteScratchpad(Page::const_span data, Variant variant);
 
-  Core::error_code doReadBlockProtection(int blockNum,
-                                         BlockProtection & protection,
-                                         Variant variant) const;
+  Core::Result<Page::array> doReadScratchpad(Variant variant) const;
+
+  Core::Result<BlockProtection> doReadBlockProtection(int blockNum,
+                                                      Variant variant) const;
 
-  Core::error_code doWriteAuthSegment(int pageNum, int segmentNum,
-                                      Segment::const_span newData,
-                                      Page::const_span mac, Variant variant);
+  Core::Result<void> 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::Result<void> doContinueWriteAuthSegment(Segment::const_span newData,
+                                                Page::const_span mac,
+                                                Variant variant);
 
-  Core::error_code
+  Core::Result<void>
   doReadAllBlockProtection(Core::span<BlockProtection> protection,
                            Variant variant) const;
 
-  Core::error_code doLoadSecret(bool lock, bool lowPower);
+  Core::Result<void> doLoadSecret(bool lock, bool lowPower);
 
-  Core::error_code doComputeSecret(int pageNum, bool lock, bool lowPower);
+  Core::Result<void> doComputeSecret(int pageNum, bool lock, bool lowPower);
 
 private:
   enum Command {
@@ -225,11 +224,11 @@
     AuthWriteBlockProtection = 0xCC,
   };
 
-  Core::error_code doWriteAuthSegment(Segment::const_span newData,
-                                      Page::const_span mac, Variant variant,
-                                      bool continuing);
+  Core::Result<void> doWriteAuthSegment(Segment::const_span newData,
+                                        Page::const_span mac, Variant variant,
+                                        bool continuing);
 
-  Core::error_code
+  Core::Result<void>
   writeCommandWithCrc(Command command, uint_least8_t parameter,
                       Core::OneWireMaster::Level level =
                           Core::OneWireMaster::NormalLevel) const;
@@ -239,6 +238,16 @@
   Core::Sleep * sleep;
 };
 
+} // namespace MaximInterfaceDevices
+namespace MaximInterfaceCore {
+
+template <>
+struct is_error_code_enum<MaximInterfaceDevices::DS28E15_22_25::ErrorValue>
+    : true_type {};
+
+} // namespace MaximInterfaceCore
+namespace MaximInterfaceDevices {
+
 inline Core::error_code make_error_code(DS28E15_22_25::ErrorValue e) {
   return Core::error_code(e, DS28E15_22_25::errorCategory());
 }
@@ -256,41 +265,41 @@
 
   /// @brief Perform Write Scratchpad operation on the device.
   /// @param[in] data Data to write to the scratchpad.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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;
+  /// @returns Buffer to read data from the scratchpad into.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array> readScratchpad() 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;
+  /// @returns Receives protection status read from device.
+  MaximInterfaceDevices_EXPORT Core::Result<BlockProtection>
+  readBlockProtection(int blockNum) 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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;
+  /// @returns Receives protection statuses read from device.
+  MaximInterfaceDevices_EXPORT
+      Core::Result<Core::array<BlockProtection, protectionBlocks> >
+      readAllBlockProtection() const;
 };
 
 /// Interface to the DS28E15 authenticator.
@@ -304,14 +313,14 @@
   /// @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);
+  MaximInterfaceDevices_EXPORT Core::Result<void> 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);
+  MaximInterfaceDevices_EXPORT Core::Result<void> computeSecret(int pageNum,
+                                                                bool lock);
 };
 
 /// Interface to the DS28EL22 (low power) authenticator.
@@ -327,41 +336,41 @@
 
   /// @brief Perform Write Scratchpad operation on the device.
   /// @param[in] data Data to write to the scratchpad.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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;
+  /// @returns Buffer to read data from the scratchpad into.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array> readScratchpad() 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;
+  /// @returns Receives protection status read from device.
+  MaximInterfaceDevices_EXPORT Core::Result<BlockProtection>
+  readBlockProtection(int blockNum) 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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;
+  /// @returns Receives protection statuses read from device.
+  MaximInterfaceDevices_EXPORT
+      Core::Result<Core::array<BlockProtection, protectionBlocks> >
+      readAllBlockProtection() const;
 };
 
 /// Interface to the DS28E22 authenticator.
@@ -375,14 +384,14 @@
   /// @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);
+  MaximInterfaceDevices_EXPORT Core::Result<void> 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);
+  MaximInterfaceDevices_EXPORT Core::Result<void> computeSecret(int pageNum,
+                                                                bool lock);
 };
 
 /// Interface to the DS28EL25 (low power) authenticator.
@@ -398,41 +407,41 @@
 
   /// @brief Perform Write Scratchpad operation on the device.
   /// @param[in] data Data to write to the scratchpad.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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;
+  /// @returns Buffer to read data from the scratchpad into.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array> readScratchpad() 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;
+  /// @returns Receives protection status read from device.
+  MaximInterfaceDevices_EXPORT Core::Result<BlockProtection>
+  readBlockProtection(int blockNum) 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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;
+  /// @returns Receives protection statuses read from device.
+  MaximInterfaceDevices_EXPORT
+      Core::Result<Core::array<BlockProtection, protectionBlocks> >
+      readAllBlockProtection() const;
 };
 
 /// Interface to the DS28E25 authenticator.
@@ -445,14 +454,14 @@
   /// @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);
+  MaximInterfaceDevices_EXPORT Core::Result<void> 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);
+  MaximInterfaceDevices_EXPORT Core::Result<void> computeSecret(int pageNum,
+                                                                bool lock);
 };
 
 /// Represents the status of a memory protection block.
@@ -523,20 +532,11 @@
   static const unsigned int readProtectionMask = 0x80,
                             writeProtectionMask = 0x40,
                             eepromEmulationMask = 0x20,
-                            authProtectionMask = 0x10, blockNumMask = 0x0F;
+                            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:
@@ -666,14 +666,12 @@
   /// @}
 
 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;
+  static const size_t romIdIdx = 0;
+  static const size_t manIdIdx = romIdIdx + Core::RomId::size;
+  static const size_t pageNumIdx = manIdIdx + Core::ManId::size;
+  static const size_t segmentNumIdx = pageNumIdx + 1;
+  static const size_t oldDataIdx = segmentNumIdx + 1;
+  static const size_t newDataIdx = oldDataIdx + Segment::size;
 
   Result::array result_;
 };
@@ -759,13 +757,11 @@
   /// @}
 
 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;
+  static const size_t romIdIdx = 0;
+  static const size_t manIdIdx = romIdIdx + Core::RomId::size;
+  static const size_t blockNumIdx = manIdIdx + Core::ManId::size;
+  static const size_t oldProtectionIdx = blockNumIdx + 2;
+  static const size_t newProtectionIdx = oldProtectionIdx + 4;
 
   Result::array result_;
   BlockProtection oldProtection_;
@@ -893,13 +889,11 @@
   /// @}
 
 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;
+  static const size_t pageIdx = 0;
+  static const size_t scratchpadIdx = pageIdx + Page::size;
+  static const size_t romIdIdx = scratchpadIdx + Page::size;
+  static const size_t manIdIdx = romIdIdx + Core::RomId::size;
+  static const size_t pageNumIdx = manIdIdx + Core::ManId::size;
 
   Result::array result_;
 };
--- a/MaximInterfaceDevices/DS28E16.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS28E16.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -50,9 +50,9 @@
 const int DS28E16::masterSecretPage;
 const int DS28E16::memoryPages;
 
-error_code DS28E16::writeMemory(int pageNum, Page::const_span page) {
+Result<void> DS28E16::writeMemory(int pageNum, Page::const_span page) {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   uint_least8_t request[2 + Page::size];
@@ -62,49 +62,51 @@
   return runCommand(request, writeMemoryTimeMs);
 }
 
-error_code DS28E16::readMemory(int pageNum, Page::span page) {
+Result<DS28E16::Page::array> DS28E16::readMemory(int pageNum) const {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return 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());
+  Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, 2), readMemoryTimeMs, buffer);
+  if (!response) {
+    return response.error();
   }
-  return result;
+  Page::array page;
+  response.value() = response.value().first(Page::size);
+  copy(response.value().begin(), response.value().end(), page.begin());
+  return page;
 }
 
-error_code DS28E16::readStatus(Status & status) {
-  uint_least8_t buffer[1 + Status::PageProtectionList::csize + 2];
+Result<DS28E16::Status> DS28E16::readStatus() const {
+  uint_least8_t buffer[1 + Status::PageProtectionList::size + 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;
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, 1), readMemoryTimeMs, buffer);
+  if (!response) {
+    return response.error();
+  }
+  Status status;
+  span<uint_least8_t>::const_iterator responseIt = response.value().begin();
+  for (Status::PageProtectionList::array::iterator it =
+           status.pageProtection.begin();
+       it != status.pageProtection.end(); ++it) {
+    *it = *responseIt;
     ++responseIt;
-    status.deviceVersion = *responseIt;
   }
-  return result;
+  status.manId = *responseIt;
+  ++responseIt;
+  status.deviceVersion = *responseIt;
+  return status;
 }
 
-error_code DS28E16::setPageProtection(int pageNum,
-                                      const PageProtection & protection) {
+Result<void> DS28E16::setPageProtection(int pageNum,
+                                        const PageProtection & protection) {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const uint_least8_t request[] = {
@@ -113,12 +115,10 @@
   return runCommand(request, shortWriteMemoryTimeMs);
 }
 
-error_code
-DS28E16::computeAndReadPageAuthentication(int pageNum, bool anonymous,
-                                          DoublePage::const_span challenge,
-                                          DoublePage::span hmac) {
+Result<DS28E16::DoublePage::array> DS28E16::computeAndReadPageAuthentication(
+    int pageNum, bool anonymous, DoublePage::const_span challenge) const {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const size_t requestSize = 3 + DoublePage::size;
@@ -131,20 +131,22 @@
   }
   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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, requestSize), computationTimeMs,
+                 make_span(buffer, responseSize));
+  if (!response) {
+    return response.error();
   }
-  return result;
+  DoublePage::array hmac;
+  copy(response.value().begin(), response.value().end(), hmac.begin());
+  return hmac;
 }
 
-error_code DS28E16::computeSecret(int bindingDataPageNum,
-                                  bool constantBindingData, bool anonymous,
-                                  DoublePage::const_span partialSecret) {
+Result<void> DS28E16::computeSecret(int bindingDataPageNum,
+                                    bool constantBindingData, bool anonymous,
+                                    DoublePage::const_span partialSecret) {
   if (bindingDataPageNum < 0 || bindingDataPageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   uint_least8_t request[3 + DoublePage::size];
@@ -161,27 +163,29 @@
   return runCommand(request, computationTimeMs);
 }
 
-error_code DS28E16::decrementCounter() {
+Result<void> DS28E16::decrementCounter() {
   const uint_least8_t request = 0xC9;
   return runCommand(make_span(&request, 1), writeMemoryTimeMs);
 }
 
-error_code DS28E16::lockOutDisableDevice() {
-  const DisableDevicePassword::array password = {};
+Result<void> DS28E16::lockOutDisableDevice() {
+  const DisableDevicePassword::array password = {0};
   return disableDevice(LockOutDisableDevice, password);
 }
 
-error_code
+Result<void>
 DS28E16::setDisableDevicePassword(DisableDevicePassword::const_span password) {
   return disableDevice(SetDisableDevicePassword, password);
 }
 
-error_code DS28E16::disableDevice(DisableDevicePassword::const_span password) {
+Result<void>
+DS28E16::disableDevice(DisableDevicePassword::const_span password) {
   return disableDevice(DisableDevice, password);
 }
 
-error_code DS28E16::disableDevice(DisableDeviceOperation operation,
-                                  DisableDevicePassword::const_span password) {
+Result<void>
+DS28E16::disableDevice(DisableDeviceOperation operation,
+                       DisableDevicePassword::const_span password) {
   const uint_least8_t request[] = {
       0x33,        static_cast<uint_least8_t>(operation),
       password[0], password[1],
@@ -191,43 +195,40 @@
   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;
+Result<span<uint_least8_t> >
+DS28E16::runCommand(span<const uint_least8_t> request, int delayTime,
+                    span<uint_least8_t> response) const {
+  const Result<span<uint_least8_t> > responseOutput =
+      doRunCommand(request, delayTime, response);
+  if (!responseOutput) {
+    return responseOutput;
   }
-  if (response.empty()) {
-    return make_error_code(InvalidResponseError);
+  if (responseOutput.value().empty()) {
+    return InvalidResponseError;
   }
   // Parse command result byte.
-  switch (response[0]) {
+  switch (responseOutput.value().front()) {
   case 0xAA:
     // Success response.
-    if (response.size() != responseInputSize) {
-      result = make_error_code(InvalidResponseError);
-    }
     break;
 
   case 0x00:
-    result = make_error_code(AuthenticationError);
-    break;
+    return AuthenticationError;
 
   default:
-    result.assign(response[0], errorCategory());
-    break;
+    return error_code(responseOutput.value().front(), errorCategory());
   }
-  response = response.subspan(1);
-  return result;
+  if (responseOutput.value().size() != response.size()) {
+    return InvalidResponseError;
+  }
+  return responseOutput.value().subspan(1);
 }
 
-error_code DS28E16::runCommand(span<const uint_least8_t> request,
-                               int delayTime) {
+Result<void> 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);
+  MaximInterfaceCore_TRY(runCommand(request, delayTime, make_span(&buffer, 1)));
+  return none;
 }
 
 const error_category & DS28E16::errorCategory() {
@@ -264,15 +265,6 @@
   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);
--- a/MaximInterfaceDevices/DS28E16.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS28E16.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceDevices_DS28E16
-#define MaximInterfaceDevices_DS28E16
+#ifndef MaximInterfaceDevices_DS28E16_hpp
+#define MaximInterfaceDevices_DS28E16_hpp
 
 #include <stdint.h>
 #include <MaximInterfaceCore/Algorithm.hpp>
@@ -91,9 +91,9 @@
   typedef Core::FlagSet<PageProtectionType, 4> PageProtection;
 
   struct Status {
-    typedef Core::array<PageProtection, memoryPages> PageProtectionList;
+    typedef Core::array_span<PageProtection, memoryPages> PageProtectionList;
 
-    PageProtectionList pageProtection;
+    PageProtectionList::array pageProtection;
     uint_least8_t manId;
     uint_least8_t deviceVersion;
   };
@@ -108,48 +108,47 @@
   /// @brief Write memory with no protection.
   /// @param pageNum Number of page to write.
   /// @param page Data to write.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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);
+  /// @returns Data that was read.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array>
+  readMemory(int pageNum) const;
 
   /// @brief Reads the current status of the device.
-  /// @param[out] status Status that was read.
-  MaximInterfaceDevices_EXPORT Core::error_code readStatus(Status & status);
+  /// @returns Status that was read.
+  MaximInterfaceDevices_EXPORT Core::Result<Status> readStatus() const;
 
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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
+  /// @returns Computed page HMAC.
+  MaximInterfaceDevices_EXPORT Core::Result<DoublePage::array>
   computeAndReadPageAuthentication(int pageNum, bool anonymous,
-                                   DoublePage::const_span challenge,
-                                   DoublePage::span hmac);
+                                   DoublePage::const_span challenge) const;
 
   /// Decrement the decrement-only counter.
-  MaximInterfaceDevices_EXPORT Core::error_code decrementCounter();
+  MaximInterfaceDevices_EXPORT Core::Result<void> decrementCounter();
 
   /// Set password that will be subsequently used to disable the device.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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();
+  MaximInterfaceDevices_EXPORT Core::Result<void> lockOutDisableDevice();
 
   /// Permanently disable the device.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   disableDevice(DisableDevicePassword::const_span password);
 
   /// @brief
@@ -162,7 +161,7 @@
   /// @note
   /// This command should be executed prior to the
   /// Compute and Read Page Authentication command.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   computeSecret(int bindingDataPageNum, bool constantBindingData,
                 bool anonymous, DoublePage::const_span partialSecret);
 
@@ -170,11 +169,11 @@
   errorCategory();
 
 protected:
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<Core::span<uint_least8_t> >
   runCommand(Core::span<const uint_least8_t> request, int delayTime,
-             Core::span<uint_least8_t> & response);
+             Core::span<uint_least8_t> response) const;
 
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   runCommand(Core::span<const uint_least8_t> request, int delayTime);
 
 private:
@@ -184,22 +183,26 @@
     DisableDevice = 0x00
   };
 
-  Core::error_code disableDevice(DisableDeviceOperation operation,
-                                 DisableDevicePassword::const_span password);
+  Core::Result<void> disableDevice(DisableDeviceOperation operation,
+                                   DisableDevicePassword::const_span password);
 
   Core::RunCommand doRunCommand;
 };
 
+} // namespace MaximInterfaceDevices
+namespace MaximInterfaceCore {
+
+template <>
+struct is_error_code_enum<MaximInterfaceDevices::DS28E16::ErrorValue>
+    : true_type {};
+
+} // namespace MaximInterfaceCore
+namespace MaximInterfaceDevices {
+
 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:
@@ -317,13 +320,11 @@
   /// @}
 
 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;
+  static const size_t romIdIdx = 0;
+  static const size_t pageIdx = romIdIdx + Core::RomId::size;
+  static const size_t challengeIdx = pageIdx + 2 * Page::size;
+  static const size_t pageNumIdx = challengeIdx + DoublePage::size;
+  static const size_t manIdIdx = pageNumIdx + 1;
 
   Result::array result_;
 };
--- a/MaximInterfaceDevices/DS28E17.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS28E17.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -31,58 +31,54 @@
 *******************************************************************************/
 
 #include <stddef.h>
-#include <MaximInterfaceCore/crc.hpp>
+#include <MaximInterfaceCore/Crc.hpp>
 #include <MaximInterfaceCore/Error.hpp>
 #include <MaximInterfaceCore/OneWireMaster.hpp>
 #include "DS28E17.hpp"
 
+#define TRY MaximInterfaceCore_TRY
+#define TRY_VALUE MaximInterfaceCore_TRY_VALUE
+
 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) {
+Result<void> DS28E17::writeDataWithStop(uint_least8_t I2C_addr,
+                                        span<const uint_least8_t> data) {
   return sendPacket(WriteDataWithStopCmd, &I2C_addr, data,
-                    span<uint_least8_t>(), wr_status);
+                    span<uint_least8_t>());
 }
 
-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);
+Result<void> DS28E17::writeDataNoStop(uint_least8_t I2C_addr,
+                                      span<const uint_least8_t> data) {
+  return sendPacket(WriteDataNoStopCmd, &I2C_addr, data, span<uint_least8_t>());
 }
 
-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);
+Result<void> DS28E17::writeDataOnly(span<const uint_least8_t> data) {
+  return sendPacket(WriteDataOnlyCmd, NULL, data, span<uint_least8_t>());
 }
 
-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);
+Result<void> DS28E17::writeDataOnlyWithStop(span<const uint_least8_t> data) {
+  return sendPacket(WriteDataOnlyWithStopCmd, NULL, data,
+                    span<uint_least8_t>());
 }
 
-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);
+Result<void>
+DS28E17::writeReadDataWithStop(uint_least8_t I2C_addr,
+                               span<const uint_least8_t> write_data,
+                               span<uint_least8_t> read_data) {
+  return sendPacket(WriteReadDataWithStopCmd, &I2C_addr, write_data, read_data);
 }
 
-error_code DS28E17::readDataWithStop(uint_least8_t I2C_addr,
-                                     span<uint_least8_t> data) {
+Result<void> DS28E17::readDataWithStop(uint_least8_t I2C_addr,
+                                       span<uint_least8_t> data) {
   return sendPacket(ReadDataWithStopCmd, &I2C_addr, span<const uint_least8_t>(),
-                    data, NULL);
+                    data);
 }
 
-error_code DS28E17::writeConfigReg(I2CSpeed speed) {
-  error_code result = selectRom(*master);
-  if (!result) {
+Result<void> DS28E17::writeConfigReg(I2CSpeed speed) {
+  Result<void> result = selectRom(*master);
+  if (result) {
     // Send CMD and Data
     const uint_least8_t send_block[] = {WriteConfigurationCmd,
                                         static_cast<uint_least8_t>(speed)};
@@ -91,97 +87,86 @@
   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;
-        }
-      }
-    }
+Result<DS28E17::I2CSpeed> DS28E17::readConfigReg() const {
+  TRY(selectRom(*master));
+  // Send CMD and receive Data
+  TRY(master->writeByte(ReadConfigurationCmd));
+  uint_least8_t config;
+  TRY_VALUE(config, master->readByte());
+  switch (config) {
+  case Speed100kHz:
+  case Speed400kHz:
+  case Speed900kHz:
+    return static_cast<I2CSpeed>(config);
   }
-  return result;
+  return OutOfRangeError;
 }
 
-error_code DS28E17::enableSleepMode() {
-  error_code result = selectRom(*master);
-  if (!result) {
+Result<void> DS28E17::enableSleepMode() {
+  Result<void> 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);
+Result<uint_least8_t> DS28E17::readDeviceRevision() const {
+  Result<void> result = selectRom(*master);
   if (!result) {
-    // Send CMD and receive Data
-    result = master->writeByte(ReadDeviceRevisionCmd);
-    if (!result) {
-      result = master->readByte(rev);
-    }
+    return result.error();
   }
-  return result;
+  result = master->writeByte(ReadDeviceRevisionCmd);
+  if (!result) {
+    return result.error();
+  }
+  return master->readByte();
 }
 
-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) {
+Result<void> DS28E17::sendPacket(Command command,
+                                 const uint_least8_t * I2C_addr,
+                                 span<const uint_least8_t> write_data,
+                                 span<uint_least8_t> read_data) {
   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);
+    return OutOfRangeError;
   }
 
-  error_code result = selectRom(*master);
-  if (result) {
+  Result<void> result = selectRom(*master);
+  if (!result) {
     return result;
   }
   uint_fast16_t crc16 = calculateCrc16(command);
   result = master->writeByte(command);
-  if (result) {
+  if (!result) {
     return result;
   }
   if (I2C_addr) {
     crc16 = calculateCrc16(crc16, *I2C_addr);
     result = master->writeByte(*I2C_addr);
-    if (result) {
+    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) {
+    if (!result) {
       return result;
     }
     crc16 = calculateCrc16(crc16, write_data);
     result = master->writeBlock(write_data);
-    if (result) {
+    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) {
+    if (!result) {
       return result;
     }
   }
@@ -189,45 +174,33 @@
   const uint_least8_t crc16Bytes[] = {static_cast<uint_least8_t>(crc16),
                                       static_cast<uint_least8_t>(crc16 >> 8)};
   result = master->writeBlock(crc16Bytes);
-  if (result) {
+  if (!result) {
     return result;
   }
   // Poll for Zero 1-Wire bit and return if an error occurs
   int poll_count = 0;
-  bool recvbit;
+  bool recvBit;
   do {
     if (poll_count++ < pollLimit) {
-      return make_error_code(TimeoutError);
-    }
-    result = master->readBit(recvbit);
-    if (result) {
-      return result;
+      return TimeoutError;
     }
-  } while (recvbit);
+    TRY_VALUE(recvBit, master->readBit());
+  } while (recvBit);
   uint_least8_t status;
-  result = master->readByte(status);
-  if (result) {
-    return result;
-  }
+  TRY_VALUE(status, master->readByte());
   if ((status & 0x1) == 0x1) {
-    return make_error_code(InvalidCrc16Error);
+    return InvalidCrc16Error;
   }
   if ((status & 0x2) == 0x2) {
-    return make_error_code(AddressNackError);
+    return AddressNackError;
   }
   if ((status & 0x8) == 0x8) {
-    return make_error_code(InvalidStartError);
+    return InvalidStartError;
   }
   if (!write_data.empty()) {
-    result = master->readByte(status);
-    if (result) {
-      return result;
-    }
-    if (wr_status) {
-      *wr_status = status;
-    }
+    TRY_VALUE(status, master->readByte());
     if (status != 0) {
-      return make_error_code(WriteNackError);
+      return error_code(status, errorCategory());
     }
   }
   if (!read_data.empty()) {
@@ -257,13 +230,11 @@
 
       case InvalidStartError:
         return "Invalid Start Error";
-
-      case WriteNackError:
+      }
+      if (condition >= 1 && condition <= 255) {
         return "Write Nack Error";
-
-      default:
-        return defaultErrorMessage(condition);
       }
+      return defaultErrorMessage(condition);
     }
   } instance;
   return instance;
--- a/MaximInterfaceDevices/DS28E17.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS28E17.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceDevices_DS28E17
-#define MaximInterfaceDevices_DS28E17
+#ifndef MaximInterfaceDevices_DS28E17_hpp
+#define MaximInterfaceDevices_DS28E17_hpp
 
 #include <stdint.h>
 #include <MaximInterfaceCore/SelectRom.hpp>
@@ -55,13 +55,13 @@
 /// provides 1-Wire access for a single I2C interface.
 class DS28E17 {
 public:
+  // Values from 1-255 represent the Write Status byte.
   enum ErrorValue {
-    TimeoutError = 1,
+    TimeoutError = 256,
     OutOfRangeError,
     InvalidCrc16Error,
     AddressNackError,
-    InvalidStartError,
-    WriteNackError
+    InvalidStartError
   };
 
   enum I2CSpeed { Speed100kHz, Speed400kHz, Speed900kHz };
@@ -81,14 +81,12 @@
   /// 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
+  /// @returns
+  /// Values from 1-255 in the DS28E17 category represent the Write Status
+  /// indicating which write byte did not acknowledge.
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   writeDataWithStop(uint_least8_t I2C_addr,
-                    Core::span<const uint_least8_t> data,
-                    uint_least8_t * wr_status = NULL);
+                    Core::span<const uint_least8_t> data);
 
   /// @brief Write Data No Stop command.
   /// @details Output on I2C: S, Address + Write, Write Data [1-255]
@@ -96,35 +94,29 @@
   /// 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);
+  /// @returns
+  /// Values from 1-255 in the DS28E17 category represent the Write Status
+  /// indicating which write byte did not acknowledge.
+  MaximInterfaceDevices_EXPORT Core::Result<void>
+  writeDataNoStop(uint_least8_t I2C_addr, Core::span<const uint_least8_t> data);
 
   /// @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);
+  /// @returns
+  /// Values from 1-255 in the DS28E17 category represent the Write Status
+  /// indicating which write byte did not acknowledge.
+  MaximInterfaceDevices_EXPORT Core::Result<void>
+  writeDataOnly(Core::span<const uint_least8_t> data);
 
   /// @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);
+  /// @returns
+  /// Values from 1-255 in the DS28E17 category represent the Write Status
+  /// indicating which write byte did not acknowledge.
+  MaximInterfaceDevices_EXPORT Core::Result<void>
+  writeDataOnlyWithStop(Core::span<const uint_least8_t> data);
 
   /// @brief Write, Read Data With Stop command.
   /// @details Output on I2C:
@@ -135,13 +127,13 @@
   /// 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);
+  /// @returns
+  /// Values from 1-255 in the DS28E17 category represent the Write Status
+  /// indicating which write byte did not acknowledge.
+  MaximInterfaceDevices_EXPORT Core::Result<void>
+  writeReadDataWithStop(uint_least8_t I2C_addr,
+                        Core::span<const uint_least8_t> write_data,
+                        Core::span<uint_least8_t> read_data);
 
   /// @brief Read Data With Stop command.
   /// @details Output on I2C:
@@ -150,28 +142,29 @@
   /// 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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);
+  MaximInterfaceDevices_EXPORT Core::Result<void>
+  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);
+  /// @returns speed Speed read from configuration register.
+  MaximInterfaceDevices_EXPORT Core::Result<I2CSpeed> readConfigReg() const;
 
   /// @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();
+  MaximInterfaceDevices_EXPORT Core::Result<void> 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);
+  /// @returns Device Revision.
+  MaximInterfaceDevices_EXPORT Core::Result<uint_least8_t>
+  readDeviceRevision() const;
 
   MaximInterfaceDevices_EXPORT static const Core::error_category &
   errorCategory();
@@ -190,15 +183,24 @@
     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::Result<void> sendPacket(Command command, const uint_least8_t * I2C_addr,
+                                Core::span<const uint_least8_t> write_data,
+                                Core::span<uint_least8_t> read_data);
 
   Core::SelectRom selectRom;
   Core::OneWireMaster * master;
 };
 
+} // namespace MaximInterfaceDevices
+namespace MaximInterfaceCore {
+
+template <>
+struct is_error_code_enum<MaximInterfaceDevices::DS28E17::ErrorValue>
+    : true_type {};
+
+} // namespace MaximInterfaceCore
+namespace MaximInterfaceDevices {
+
 inline Core::error_code make_error_code(DS28E17::ErrorValue e) {
   return Core::error_code(e, DS28E17::errorCategory());
 }
--- a/MaximInterfaceDevices/DS28E38.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS28E38.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -54,9 +54,9 @@
 const int DS28E38::privateKeyPage;
 const int DS28E38::memoryPages;
 
-error_code DS28E38::writeMemory(int pageNum, Page::const_span page) {
+Result<void> DS28E38::writeMemory(int pageNum, Page::const_span page) {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   uint_least8_t request[2 + Page::size];
@@ -66,69 +66,71 @@
   return runCommand(request, writeMemoryTimeMs);
 }
 
-error_code DS28E38::readMemory(int pageNum, Page::span page) {
+Result<DS28E38::Page::array> DS28E38::readMemory(int pageNum) const {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return 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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, 2), readMemoryTimeMs, buffer);
+  if (!response) {
+    return response.error();
   }
-  return result;
+  Page::array page;
+  copy(response.value().begin(), response.value().end(), page.begin());
+  return page;
 }
 
-error_code DS28E38::readStatus(bool entropyHealthTest, Status & status) {
+Result<DS28E38::Status> DS28E38::readStatus(bool entropyHealthTest) const {
   int delay = readMemoryTimeMs;
   if (entropyHealthTest) {
     delay += trngOnDemandCheckTimeMs;
   }
-  uint_least8_t buffer[Status::PageProtectionList::csize + ManId::size +
-                       Status::RomVersion::csize + 2];
+  uint_least8_t buffer[Status::PageProtectionList::size + ManId::size +
+                       Status::RomVersion::size + 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;
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, 2), delay, buffer);
+  if (!response) {
+    return response.error();
+  }
+  Status status;
+  span<uint_least8_t>::const_iterator responseIt = response.value().begin();
+  for (Status::PageProtectionList::array::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;
-    }
+  default:
+    return InvalidResponseError;
   }
-  return result;
+  return status;
 }
 
-error_code DS28E38::setPageProtection(int pageNum,
-                                      const PageProtection & protection) {
+Result<void> DS28E38::setPageProtection(int pageNum,
+                                        const PageProtection & protection) {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   int delay = writeStateTimeMs;
@@ -141,12 +143,11 @@
   return runCommand(request, delay);
 }
 
-error_code
+Result<Ecc256::Signature::array>
 DS28E38::computeAndReadPageAuthentication(int pageNum, bool anonymous,
-                                          Page::const_span challenge,
-                                          Ecc256::Signature::span signature) {
+                                          Page::const_span challenge) const {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const size_t requestSize = 2 + Page::size;
@@ -155,33 +156,35 @@
   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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, requestSize), generateEcdsaSignatureTimeMs,
+                 make_span(buffer, responseSize));
+  if (!response) {
+    return response.error();
   }
-  return result;
+  Ecc256::Signature::array signature;
+  span<uint_least8_t>::const_iterator begin = response.value().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 signature;
 }
 
-error_code DS28E38::decrementCounter() {
+Result<void> DS28E38::decrementCounter() {
   const uint_least8_t request = 0xC9;
   return runCommand(make_span(&request, 1), writeMemoryTimeMs);
 }
 
-error_code DS28E38::disableDevice() {
+Result<void> 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) {
+Result<void> DS28E38::generateEcc256KeyPair(bool privateKeyPuf,
+                                            bool writeProtectEnable) {
   int delay = generateEccKeyPairTimeMs;
   if (writeProtectEnable) {
     delay += writeStateTimeMs;
@@ -196,61 +199,59 @@
   return runCommand(request, delay);
 }
 
-error_code DS28E38::readRng(span<uint_least8_t> data) {
+Result<void> DS28E38::readRng(span<uint_least8_t> data) const {
   const span<uint_least8_t>::index_type maxDataSize = 64;
   if ((data.size() < 1) || (data.size() > maxDataSize)) {
-    return make_error_code(InvalidParameterError);
+    return 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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, 2), trngGenerationTimeMs,
+                 make_span(buffer, 1 + data.size()));
+  if (!response) {
+    return response.error();
   }
-  return result;
+  copy(response.value().begin(), response.value().end(), data.begin());
+  return none;
 }
 
-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;
+Result<span<uint_least8_t> >
+DS28E38::runCommand(span<const uint_least8_t> request, int delayTime,
+                    span<uint_least8_t> response) const {
+  const Result<span<uint_least8_t> > responseOutput =
+      doRunCommand(request, delayTime, response);
+  if (!responseOutput) {
+    return responseOutput;
   }
-  if (response.empty()) {
-    return make_error_code(InvalidResponseError);
+  if (responseOutput.value().empty()) {
+    return InvalidResponseError;
   }
   // Parse command result byte.
-  switch (response[0]) {
+  switch (responseOutput.value().front()) {
   case 0xAA:
     // Success response.
-    if (response.size() != responseInputSize) {
-      result = make_error_code(InvalidResponseError);
-    }
     break;
 
   case 0x00:
-    result = make_error_code(InvalidResponseError);
-    break;
+    return InvalidResponseError;
 
   default:
-    result.assign(response[0], errorCategory());
-    break;
+    return error_code(responseOutput.value().front(), errorCategory());
   }
-  response = response.subspan(1);
-  return result;
+  if (responseOutput.value().size() != response.size()) {
+    return InvalidResponseError;
+  }
+  return responseOutput.value().subspan(1);
 }
 
-error_code DS28E38::runCommand(span<const uint_least8_t> request,
-                               int delayTime) {
+Result<void> 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);
+  MaximInterfaceCore_TRY(runCommand(request, delayTime, make_span(&buffer, 1)));
+  return none;
 }
 
 const error_category & DS28E38::errorCategory() {
@@ -284,15 +285,6 @@
   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);
--- a/MaximInterfaceDevices/DS28E38.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS28E38.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceDevices_DS28E38
-#define MaximInterfaceDevices_DS28E38
+#ifndef MaximInterfaceDevices_DS28E38_hpp
+#define MaximInterfaceDevices_DS28E38_hpp
 
 #include <stdint.h>
 #include <MaximInterfaceCore/Algorithm.hpp>
@@ -94,12 +94,12 @@
       EntropyNotHealthy = 0xDD
     };
 
-    typedef Core::array<PageProtection, memoryPages> PageProtectionList;
-    typedef Core::array<uint_least8_t, 2> RomVersion;
+    typedef Core::array_span<PageProtection, memoryPages> PageProtectionList;
+    typedef Core::array_span<uint_least8_t, 2> RomVersion;
 
-    PageProtectionList pageProtection;
+    PageProtectionList::array pageProtection;
     Core::ManId::array manId;
-    RomVersion romVersion;
+    RomVersion::array romVersion;
     EntropyHealthTestStatus entropyHealthTestStatus;
   };
 
@@ -113,81 +113,84 @@
   /// @brief Write memory with no protection.
   /// @param pageNum Number of page to write.
   /// @param page Data to write.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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);
+  /// @returns Data that was read.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array>
+  readMemory(int pageNum) const;
 
   /// @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);
+  /// @returns status Status that was read.
+  MaximInterfaceDevices_EXPORT Core::Result<Status>
+  readStatus(bool entropyHealthTest) const;
 
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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
+  /// @returns Computed page signature.
+  MaximInterfaceDevices_EXPORT Core::Result<Core::Ecc256::Signature::array>
   computeAndReadPageAuthentication(int pageNum, bool anonymous,
-                                   Page::const_span challenge,
-                                   Core::Ecc256::Signature::span signature);
+                                   Page::const_span challenge) const;
 
   /// Decrement the decrement-only counter.
-  MaximInterfaceDevices_EXPORT Core::error_code decrementCounter();
+  MaximInterfaceDevices_EXPORT Core::Result<void> decrementCounter();
 
   /// Permanently disable the device.
-  MaximInterfaceDevices_EXPORT Core::error_code disableDevice();
+  MaximInterfaceDevices_EXPORT Core::Result<void> 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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 Core::Result<void>
+  readRng(Core::span<uint_least8_t> data) const;
 
   MaximInterfaceDevices_EXPORT static const Core::error_category &
   errorCategory();
 
 protected:
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<Core::span<uint_least8_t> >
   runCommand(Core::span<const uint_least8_t> request, int delayTime,
-             Core::span<uint_least8_t> & response);
+             Core::span<uint_least8_t> response) const;
 
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   runCommand(Core::span<const uint_least8_t> request, int delayTime);
 
 private:
   Core::RunCommand doRunCommand;
 };
 
+} // namespace MaximInterfaceDevices
+namespace MaximInterfaceCore {
+
+template <>
+struct is_error_code_enum<MaximInterfaceDevices::DS28E38::ErrorValue>
+    : true_type {};
+
+} // namespace MaximInterfaceCore
+namespace MaximInterfaceDevices {
+
 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:
@@ -307,13 +310,11 @@
   /// @}
 
 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;
+  static const size_t romIdIdx = 0;
+  static const size_t pageIdx = romIdIdx + Core::RomId::size;
+  static const size_t challengeIdx = pageIdx + Page::size;
+  static const size_t pageNumIdx = challengeIdx + Page::size;
+  static const size_t manIdIdx = pageNumIdx + 1;
 
   Result::array result_;
 };
--- a/MaximInterfaceDevices/DS28E39.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS28E39.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -56,9 +56,9 @@
 const int DS28E39::writePublicKeyYPage;
 const int DS28E39::memoryPages;
 
-error_code DS28E39::writeMemory(int pageNum, Page::const_span page) {
+Result<void> DS28E39::writeMemory(int pageNum, Page::const_span page) {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   uint_least8_t request[2 + Page::size];
@@ -68,69 +68,71 @@
   return runCommand(request, writeMemoryTimeMs);
 }
 
-error_code DS28E39::readMemory(int pageNum, Page::span page) {
+Result<DS28E39::Page::array> DS28E39::readMemory(int pageNum) const {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return 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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, 2), readMemoryTimeMs, buffer);
+  if (!response) {
+    return response.error();
   }
-  return result;
+  Page::array page;
+  copy(response.value().begin(), response.value().end(), page.begin());
+  return page;
 }
 
-error_code DS28E39::readStatus(bool entropyHealthTest, Status & status) {
+Result<DS28E39::Status> DS28E39::readStatus(bool entropyHealthTest) const {
   int delay = readMemoryTimeMs;
   if (entropyHealthTest) {
     delay += trngOnDemandCheckTimeMs;
   }
-  uint_least8_t buffer[Status::PageProtectionList::csize + ManId::size +
-                       Status::RomVersion::csize + 2];
+  uint_least8_t buffer[Status::PageProtectionList::size + ManId::size +
+                       Status::RomVersion::size + 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;
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, 2), delay, buffer);
+  if (!response) {
+    return response.error();
+  }
+  Status status;
+  span<uint_least8_t>::const_iterator responseIt = response.value().begin();
+  for (Status::PageProtectionList::array::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;
-    }
+  default:
+    return InvalidResponseError;
   }
-  return result;
+  return status;
 }
 
-error_code DS28E39::setPageProtection(int pageNum,
-                                      const PageProtection & protection) {
+Result<void> DS28E39::setPageProtection(int pageNum,
+                                        const PageProtection & protection) {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   int delay = writeStateTimeMs;
@@ -143,12 +145,11 @@
   return runCommand(request, delay);
 }
 
-error_code
+Result<Ecc256::Signature::array>
 DS28E39::computeAndReadPageAuthentication(int pageNum, bool anonymous,
-                                          Page::const_span challenge,
-                                          Ecc256::Signature::span signature) {
+                                          Page::const_span challenge) const {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const size_t requestSize = 2 + Page::size;
@@ -157,68 +158,71 @@
   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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, requestSize), generateEcdsaSignatureTimeMs,
+                 make_span(buffer, responseSize));
+  if (!response) {
+    return response.error();
   }
-  return result;
+  Ecc256::Signature::array signature;
+  span<uint_least8_t>::const_iterator begin = response.value().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 signature;
 }
 
-error_code DS28E39::decrementCounter() {
+Result<void> DS28E39::decrementCounter() {
   const uint_least8_t request = 0xC9;
   return runCommand(make_span(&request, 1), writeMemoryTimeMs);
 }
 
-error_code DS28E39::disableDevice() {
+Result<void> 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) {
+Result<Ecc256::PublicKey::array> DS28E39::readDevicePublicKey() const {
   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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, 1), generateEccKeyPairTimeMs, buffer);
+  if (!response) {
+    return response.error();
   }
-  return result;
+  Ecc256::PublicKey::array devicePublicKey;
+  span<uint_least8_t>::const_iterator begin = response.value().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 devicePublicKey;
 }
 
-error_code DS28E39::readRng(span<uint_least8_t> data) {
+Result<void> DS28E39::readRng(span<uint_least8_t> data) const {
   const span<uint_least8_t>::index_type maxDataSize = 64;
   if ((data.size() < 1) || (data.size() > maxDataSize)) {
-    return make_error_code(InvalidParameterError);
+    return 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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, 2), trngGenerationTimeMs,
+                 make_span(buffer, 1 + data.size()));
+  if (!response) {
+    return response.error();
   }
-  return result;
+  copy(response.value().begin(), response.value().end(), data.begin());
+  return none;
 }
 
-error_code
+Result<void>
 DS28E39::authenticatePublicKey(Ecc256::Signature::const_span certificate,
                                span<const uint_least8_t> customization) {
   static const span<const uint_least8_t>::index_type maxCustomizationSize = 32;
@@ -226,7 +230,7 @@
       2 * Ecc256::Scalar::size;
 
   if (customization.size() < 1 || customization.size() > maxCustomizationSize) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   uint_least8_t request[1 + signatureSize + maxCustomizationSize];
@@ -238,11 +242,11 @@
   return runCommand(make_span(request, requestIt), verifyEcdsaSignatureTimeMs);
 }
 
-error_code
+Result<void>
 DS28E39::authenticatedWriteMemory(int pageNum, Page::const_span page,
                                   Ecc256::Signature::const_span signature) {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   uint_least8_t request[2 + Page::size + 2 * Ecc256::Scalar::size];
@@ -255,43 +259,40 @@
   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;
+Result<span<uint_least8_t> >
+DS28E39::runCommand(span<const uint_least8_t> request, int delayTime,
+                    span<uint_least8_t> response) const {
+  const Result<span<uint_least8_t> > responseOutput =
+      doRunCommand(request, delayTime, response);
+  if (!responseOutput) {
+    return responseOutput;
   }
-  if (response.empty()) {
-    return make_error_code(InvalidResponseError);
+  if (responseOutput.value().empty()) {
+    return InvalidResponseError;
   }
   // Parse command result byte.
-  switch (response[0]) {
+  switch (responseOutput.value().front()) {
   case 0xAA:
     // Success response.
-    if (response.size() != responseInputSize) {
-      result = make_error_code(InvalidResponseError);
-    }
     break;
 
   case 0x00:
-    result = make_error_code(AuthenticationError);
-    break;
+    return AuthenticationError;
 
   default:
-    result.assign(response[0], errorCategory());
-    break;
+    return error_code(responseOutput.value().front(), errorCategory());
   }
-  response = response.subspan(1);
-  return result;
+  if (responseOutput.value().size() != response.size()) {
+    return InvalidResponseError;
+  }
+  return responseOutput.value().subspan(1);
 }
 
-error_code DS28E39::runCommand(span<const uint_least8_t> request,
-                               int delayTime) {
+Result<void> 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);
+  MaximInterfaceCore_TRY(runCommand(request, delayTime, make_span(&buffer, 1)));
+  return none;
 }
 
 const error_category & DS28E39::errorCategory() {
@@ -328,15 +329,6 @@
   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);
--- a/MaximInterfaceDevices/DS28E39.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS28E39.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceDevices_DS28E39
-#define MaximInterfaceDevices_DS28E39
+#ifndef MaximInterfaceDevices_DS28E39_hpp
+#define MaximInterfaceDevices_DS28E39_hpp
 
 #include <stdint.h>
 #include <MaximInterfaceCore/Algorithm.hpp>
@@ -98,12 +98,14 @@
       EntropyNotHealthy = 0xDD
     };
 
-    typedef Core::array<PageProtection, memoryPages - 2> PageProtectionList;
-    typedef Core::array<uint_least8_t, 2> RomVersion;
+    typedef Core::array_span<PageProtection, memoryPages - 2>
+        PageProtectionList;
 
-    PageProtectionList pageProtection;
+    typedef Core::array_span<uint_least8_t, 2> RomVersion;
+
+    PageProtectionList::array pageProtection;
     Core::ManId::array manId;
-    RomVersion romVersion;
+    RomVersion::array romVersion;
     EntropyHealthTestStatus entropyHealthTestStatus;
   };
 
@@ -117,54 +119,53 @@
   /// @brief Write memory with no protection.
   /// @param pageNum Number of page to write.
   /// @param page Data to write.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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);
+  /// @returns Data that was read.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array>
+  readMemory(int pageNum) const;
 
   /// @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);
+  /// @returns Status that was read.
+  MaximInterfaceDevices_EXPORT Core::Result<Status>
+  readStatus(bool entropyHealthTest) const;
 
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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
+  /// @returns Computed page signature.
+  MaximInterfaceDevices_EXPORT Core::Result<Core::Ecc256::Signature::array>
   computeAndReadPageAuthentication(int pageNum, bool anonymous,
-                                   Page::const_span challenge,
-                                   Core::Ecc256::Signature::span signature);
+                                   Page::const_span challenge) const;
 
   /// Decrement the decrement-only counter.
-  MaximInterfaceDevices_EXPORT Core::error_code decrementCounter();
+  MaximInterfaceDevices_EXPORT Core::Result<void> decrementCounter();
 
   /// Permanently disable the device.
-  MaximInterfaceDevices_EXPORT Core::error_code disableDevice();
+  MaximInterfaceDevices_EXPORT Core::Result<void> 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);
+  /// @returns Device Public Key
+  MaximInterfaceDevices_EXPORT Core::Result<Core::Ecc256::PublicKey::array>
+  readDevicePublicKey() const;
 
   /// @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 Core::Result<void>
+  readRng(Core::span<uint_least8_t> data) const;
 
   /// @brief
   /// Authenticate a public key for authenticated writes using the
@@ -173,7 +174,7 @@
   /// 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   authenticatePublicKey(Core::Ecc256::Signature::const_span certificate,
                         Core::span<const uint_least8_t> customization);
 
@@ -181,7 +182,7 @@
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   authenticatedWriteMemory(int pageNum, Page::const_span page,
                            Core::Ecc256::Signature::const_span signature);
 
@@ -189,27 +190,31 @@
   errorCategory();
 
 protected:
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<Core::span<uint_least8_t> >
   runCommand(Core::span<const uint_least8_t> request, int delayTime,
-             Core::span<uint_least8_t> & response);
+             Core::span<uint_least8_t> response) const;
 
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   runCommand(Core::span<const uint_least8_t> request, int delayTime);
 
 private:
   Core::RunCommand doRunCommand;
 };
 
+} // namespace MaximInterfaceDevices
+namespace MaximInterfaceCore {
+
+template <>
+struct is_error_code_enum<MaximInterfaceDevices::DS28E39::ErrorValue>
+    : true_type {};
+
+} // namespace MaximInterfaceCore
+namespace MaximInterfaceDevices {
+
 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:
@@ -329,13 +334,11 @@
   /// @}
 
 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;
+  static const size_t romIdIdx = 0;
+  static const size_t pageIdx = romIdIdx + Core::RomId::size;
+  static const size_t challengeIdx = pageIdx + Page::size;
+  static const size_t pageNumIdx = challengeIdx + Page::size;
+  static const size_t manIdIdx = pageNumIdx + 1;
 
   Result::array result_;
 };
--- a/MaximInterfaceDevices/DS28E83_DS28E84.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS28E83_DS28E84.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -39,6 +39,7 @@
 
 using namespace Core;
 using std::copy;
+using std::pair;
 
 static const int readMemoryTimeMs = 2;
 static const int writeMemoryTimeMs = 100;
@@ -84,9 +85,9 @@
 const int DS28E84::memoryPages;
 const int DS28E84::protectionBlocks;
 
-error_code DS28E83_DS28E84::writeMemory(int pageNum, Page::const_span page) {
+Result<void> DS28E83_DS28E84::writeMemory(int pageNum, Page::const_span page) {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   uint_least8_t request[2 + Page::size];
@@ -96,28 +97,30 @@
   return runCommand(request, writeMemoryTimeMs);
 }
 
-error_code DS28E83_DS28E84::readMemory(int pageNum, Page::span page) {
+Result<DS28E83_DS28E84::Page::array>
+DS28E83_DS28E84::readMemory(int pageNum) const {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return 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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, 2), readMemoryTimeMs, buffer);
+  if (!response) {
+    return response.error();
   }
-  return result;
+  Page::array page;
+  copy(response.value().begin(), response.value().end(), page.begin());
+  return page;
 }
 
-error_code DS28E83_DS28E84::encryptedReadMemory(
-    int pageNum, KeySecret secret,
-    EncryptionChallenge::span encryptionChallenge, Page::span encryptedPage) {
+Result<pair<DS28E83_DS28E84::EncryptionChallenge::array,
+            DS28E83_DS28E84::Page::array> >
+DS28E83_DS28E84::encryptedReadMemory(int pageNum, KeySecret secret) const {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const size_t requestSize = 3;
@@ -126,27 +129,27 @@
   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());
+  const Result<span<uint_least8_t> > response = runCommand(
+      make_span(buffer, requestSize), readMemoryTimeMs + computeTimeMs,
+      make_span(buffer, responseSize));
+  if (!response) {
+    return response.error();
   }
-  return result;
+  pair<EncryptionChallenge::array, Page::array> data;
+  span<uint_least8_t>::const_iterator begin = response.value().begin();
+  span<uint_least8_t>::const_iterator end = begin + data.first.size();
+  copy(begin, end, data.first.begin());
+  begin = end;
+  end = begin + data.second.size();
+  copy(begin, end, data.second.begin());
+  return data;
 }
 
-error_code DS28E83_DS28E84::readBlockProtection(int blockNumber,
-                                                Optional<KeySecret> & keySecret,
-                                                BlockProtection & protection) {
+Result<pair<Optional<DS28E83_DS28E84::KeySecret>,
+            DS28E83_DS28E84::BlockProtection> >
+DS28E83_DS28E84::readBlockProtection(int blockNumber) const {
   if (blockNumber < 0 || blockNumber >= protectionBlocks) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const size_t requestSize = 2;
@@ -154,40 +157,41 @@
   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;
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, requestSize), readMemoryTimeMs,
+                 make_span(buffer, responseSize));
+  if (!response) {
+    return response.error();
   }
-  if ((response[0] & 0x3F) != blockNumber) {
-    return make_error_code(InvalidResponseError);
+  if ((response.value()[0] & 0x3F) != blockNumber) {
+    return InvalidResponseError;
   }
-  switch (response[0] >> 6) {
+  pair<Optional<KeySecret>, BlockProtection> data;
+  switch (response.value()[0] >> 6) {
   case 0:
-    keySecret = none;
+    data.first = none;
     break;
   case 1:
-    keySecret = KeySecretA;
+    data.first = KeySecretA;
     break;
   case 2:
-    keySecret = KeySecretB;
+    data.first = KeySecretB;
     break;
   default:
-    return make_error_code(InvalidResponseError);
+    return InvalidResponseError;
   }
-  if ((response[1] & 0x20) != 0) {
-    return make_error_code(InvalidResponseError);
+  if ((response.value()[1] & 0x20) != 0) {
+    return InvalidResponseError;
   }
-  protection = response[1];
-  return error_code();
+  data.second = response.value()[1];
+  return data;
 }
 
-error_code
+Result<void>
 DS28E83_DS28E84::setBlockProtection(int blockNum, KeySecret keySecret,
                                     const BlockProtection & protection) {
   if (blockNum < 0 || blockNum >= protectionBlocks || keySecret == KeySecretS) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const uint_least8_t request[] = {
@@ -198,11 +202,11 @@
   return runCommand(request, writeStateTimeMs);
 }
 
-error_code DS28E83_DS28E84::computeAndReadPageAuthentication(
-    int pageNum, KeySecret key, Page::const_span challenge,
-    Ecc256::Signature::span signature) {
+Result<Ecc256::Signature::array>
+DS28E83_DS28E84::computeAndReadEcdsaPageAuthentication(
+    int pageNum, KeySecret key, Page::const_span challenge) const {
   if (pageNum < 0 || pageNum >= memoryPages || key == KeySecretS) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const size_t requestSize = 3 + Page::size;
@@ -212,26 +216,27 @@
   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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, requestSize), generateEcdsaSignatureTimeMs,
+                 make_span(buffer, responseSize));
+  if (!response) {
+    return response.error();
   }
-  return result;
+  Ecc256::Signature::array signature;
+  span<uint_least8_t>::const_iterator begin = response.value().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 signature;
 }
 
-error_code
-DS28E83_DS28E84::computeAndReadPageAuthentication(int pageNum, KeySecret secret,
-                                                  Page::const_span challenge,
-                                                  Page::span hmac) {
+Result<DS28E83_DS28E84::Page::array>
+DS28E83_DS28E84::computeAndReadSha256PageAuthentication(
+    int pageNum, KeySecret secret, Page::const_span challenge) const {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const size_t requestSize = 3 + Page::size;
@@ -241,22 +246,24 @@
   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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, requestSize), computeTimeMs,
+                 make_span(buffer, responseSize));
+  if (!response) {
+    return response.error();
   }
-  return result;
+  Page::array hmac;
+  copy(response.value().begin(), response.value().end(), hmac.begin());
+  return hmac;
 }
 
-error_code
+Result<void>
 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);
+    return InvalidParameterError;
   }
 
   uint_least8_t buffer[2 + maxDataSize];
@@ -272,21 +279,21 @@
   return runCommand(make_span(buffer, 2 + data.size()), computeTimeMs);
 }
 
-error_code DS28E83_DS28E84::verifyEcdsaSignature(
+Result<void> 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(
+Result<void> 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
+Result<void>
 DS28E83_DS28E84::verifyEcdsaSignature(KeySecret key, bool authorityKey,
                                       GpioState gpioState,
                                       Ecc256::Signature::const_span signature) {
@@ -294,13 +301,13 @@
                               span<const uint_least8_t>());
 }
 
-error_code DS28E83_DS28E84::verifyEcdsaSignature(
+Result<void> 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);
+    return InvalidParameterError;
   }
 
   uint_least8_t request[2 + 2 * Ecc256::Scalar::size + maxBufferSize];
@@ -328,7 +335,7 @@
     }
     // else: Go to default case.
   default:
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
   *requestIt |= hashType << 3;
   if (gpioState != Unchanged) {
@@ -345,13 +352,13 @@
                         (hashType == DataInput ? computeTimeMs : 0));
 }
 
-error_code DS28E83_DS28E84::authenticateEcdsaPublicKey(
+Result<void> 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(
+Result<void> DS28E83_DS28E84::authenticateEcdsaPublicKey(
     KeySecret key, bool authWrites, Ecc256::Signature::const_span cert,
     span<const uint_least8_t> certCustomization,
     span<const uint_least8_t> ecdhCustomization) {
@@ -359,7 +366,7 @@
                                     &ecdhCustomization);
 }
 
-error_code DS28E83_DS28E84::authenticateEcdsaPublicKey(
+Result<void> 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) {
@@ -375,11 +382,11 @@
           ecdhCustomization->size() <= maxEcdhCustomizationSize &&
           certCustomization.size() + ecdhCustomization->size() <=
               maxTotalCustomizationSize)))) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   if (key == KeySecretS) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   uint_least8_t
@@ -406,14 +413,14 @@
   return runCommand(make_span(request, requestIt), delay);
 }
 
-error_code DS28E83_DS28E84::authenticatedEcdsaWriteMemory(
+Result<void> 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(
+Result<void> DS28E83_DS28E84::authenticatedEcdsaWriteMemory(
     int pageNum, bool useKeyS, Page::const_span newPageData,
     Ecc256::Signature::const_span signature,
     EncryptionChallenge::const_span challenge) {
@@ -421,12 +428,12 @@
                                        &challenge);
 }
 
-error_code DS28E83_DS28E84::authenticatedEcdsaWriteMemory(
+Result<void> 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);
+    return InvalidParameterError;
   }
 
   uint_least8_t request[2 + Page::size + 2 * Ecc256::Scalar::size +
@@ -448,7 +455,7 @@
   return runCommand(make_span(request, requestIt), delay);
 }
 
-error_code
+Result<void>
 DS28E83_DS28E84::authenticatedSha256WriteMemory(int pageNum, bool useSecretS,
                                                 Page::const_span newPageData,
                                                 Page::const_span hmac) {
@@ -456,18 +463,18 @@
                                         NULL);
 }
 
-error_code DS28E83_DS28E84::authenticatedSha256WriteMemory(
+Result<void> 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(
+Result<void> 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);
+    return InvalidParameterError;
   }
 
   uint_least8_t request[3 + 2 * Page::size + EncryptionChallenge::size];
@@ -485,11 +492,11 @@
   return runCommand(make_span(request, requestIt), delay);
 }
 
-error_code DS28E83_DS28E84::computeAndWriteSha256Secret(
+Result<void> DS28E83_DS28E84::computeAndWriteSha256Secret(
     int pageNum, KeySecret masterSecret, KeySecret destinationSecret,
     Page::const_span partialSecret) {
   if (pageNum < 0 || pageNum >= memoryPages) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   uint_least8_t request[3 + Page::size];
@@ -500,76 +507,73 @@
   return runCommand(request, writeMemoryTimeMs + computeTimeMs);
 }
 
-error_code DS28E83_DS28E84::generateEcc256KeyPair(KeySecret key) {
+Result<void> DS28E83_DS28E84::generateEcc256KeyPair(KeySecret key) {
   if (key == KeySecretS) {
-    return make_error_code(InvalidParameterError);
+    return InvalidParameterError;
   }
 
   const uint_least8_t request[] = {0xCB, key == KeySecretB};
   return runCommand(request, generateEccKeyPairTimeMs);
 }
 
-error_code DS28E83_DS28E84::readRng(span<uint_least8_t> data) {
+Result<void> DS28E83_DS28E84::readRng(span<uint_least8_t> data) const {
   const span<uint_least8_t>::index_type maxDataSize = 64;
   if ((data.size() < 1) || (data.size() > maxDataSize)) {
-    return make_error_code(InvalidParameterError);
+    return 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());
+  const Result<span<uint_least8_t> > response =
+      runCommand(make_span(buffer, 2), trngGenerationTimeMs,
+                 make_span(buffer, 1 + data.size()));
+  if (!response) {
+    return response.error();
   }
-  return result;
+  copy(response.value().begin(), response.value().end(), data.begin());
+  return none;
 }
 
-error_code DS28E83_DS28E84::entropyHealthTest() {
+Result<void> DS28E83_DS28E84::entropyHealthTest() const {
   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;
+Result<span<uint_least8_t> >
+DS28E83_DS28E84::runCommand(span<const uint_least8_t> request, int delayTime,
+                            span<uint_least8_t> response) const {
+  const Result<span<uint_least8_t> > responseOutput =
+      doRunCommand(request, delayTime, response);
+  if (!responseOutput) {
+    return responseOutput;
   }
-  if (response.empty()) {
-    return make_error_code(InvalidResponseError);
+  if (responseOutput.value().empty()) {
+    return InvalidResponseError;
   }
   // Parse command result byte.
-  switch (response[0]) {
+  switch (responseOutput.value().front()) {
   case 0xAA:
     // Success response.
-    if (response.size() != responseInputSize) {
-      result = make_error_code(InvalidResponseError);
-    }
     break;
 
   case 0x00:
-    result = make_error_code(AuthenticationError);
-    break;
+    return AuthenticationError;
 
   default:
-    result.assign(response[0], errorCategory());
-    break;
+    return error_code(responseOutput.value().front(), errorCategory());
   }
-  response = response.subspan(1);
-  return result;
+  if (responseOutput.value().size() != response.size()) {
+    return InvalidResponseError;
+  }
+  return responseOutput.value().subspan(1);
 }
 
-error_code DS28E83_DS28E84::runCommand(span<const uint_least8_t> request,
-                                       int delayTime) {
+Result<void> DS28E83_DS28E84::runCommand(span<const uint_least8_t> request,
+                                         int delayTime) const {
   uint_least8_t buffer;
-  span<uint_least8_t> response(&buffer, 1);
-  return runCommand(request, delayTime, response);
+  MaximInterfaceCore_TRY(runCommand(request, delayTime, make_span(&buffer, 1)));
+  return none;
 }
 
 const error_category & DS28E83_DS28E84::errorCategory() {
@@ -606,43 +610,30 @@
   return instance;
 }
 
-error_code DS28E84::decrementCounter() {
+Result<void> DS28E84::decrementCounter() {
   const uint_least8_t request = 0xC9;
   return runCommand(make_span(&request, 1), writeMemoryTimeMs);
 }
 
-error_code DS28E84::deviceStateControl(StateOperation operation) {
+Result<void> 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;
+Result<void> computeMultiblockHash(DS28E83_DS28E84 & device,
+                                   span<const uint_least8_t> data) {
   span<const uint_least8_t>::index_type dataIdx = 0;
-  while (dataIdx < data.size() && !result) {
+  while (dataIdx < data.size()) {
     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 =
+    MaximInterfaceCore_TRY(
         device.computeMultiblockHash(dataIdx == 0, remainingSize == chunkSize,
-                                     data.subspan(dataIdx, 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;
+  return none;
 }
 
 static void setAnonymous(RomId::span romId) {
--- a/MaximInterfaceDevices/DS28E83_DS28E84.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS28E83_DS28E84.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,10 +30,11 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceDevices_DS28E83_DS28E84
-#define MaximInterfaceDevices_DS28E83_DS28E84
+#ifndef MaximInterfaceDevices_DS28E83_DS28E84_hpp
+#define MaximInterfaceDevices_DS28E83_DS28E84_hpp
 
 #include <stdint.h>
+#include <utility>
 #include <MaximInterfaceCore/Algorithm.hpp>
 #include <MaximInterfaceCore/array_span.hpp>
 #include <MaximInterfaceCore/Ecc256.hpp>
@@ -141,38 +142,35 @@
   /// @brief Write memory with no protection.
   /// @param pageNum Number of page to write.
   /// @param page Data to write.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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);
+  /// @returns Data that was read.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array>
+  readMemory(int pageNum) const;
 
   /// @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);
+  /// @returns Encryption challenge and encrypted page data that was read.
+  MaximInterfaceDevices_EXPORT
+      Core::Result<std::pair<EncryptionChallenge::array, Page::array> >
+      encryptedReadMemory(int pageNum, KeySecret secret) const;
 
   /// @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);
+  /// @returns Secret/Key and protection set on the block.
+  MaximInterfaceDevices_EXPORT
+      Core::Result<std::pair<Core::Optional<KeySecret>, BlockProtection> >
+      readBlockProtection(int blockNum) const;
 
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   setBlockProtection(int blockNum, KeySecret keySecret,
                      const BlockProtection & protection);
 
@@ -182,11 +180,10 @@
   /// 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);
+  /// @returns Computed page signature.
+  MaximInterfaceDevices_EXPORT Core::Result<Core::Ecc256::Signature::array>
+  computeAndReadEcdsaPageAuthentication(int pageNum, KeySecret key,
+                                        Page::const_span challenge) const;
 
   /// @brief Compute and read page authentication with HMAC.
   /// @param pageNum Number of page to authenticate.
@@ -194,17 +191,17 @@
   /// 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);
+  /// @returns Computed page HMAC.
+  MaximInterfaceDevices_EXPORT Core::Result<Page::array>
+  computeAndReadSha256PageAuthentication(int pageNum, KeySecret secret,
+                                         Page::const_span challenge) const;
 
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   computeMultiblockHash(bool firstBlock, bool lastBlock,
                         Core::span<const uint_least8_t> data);
 
@@ -214,7 +211,7 @@
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState,
                        Core::Ecc256::Signature::const_span signature,
                        Core::span<const uint_least8_t> data);
@@ -225,7 +222,7 @@
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState,
                        Core::Ecc256::Signature::const_span signature,
                        Page::const_span hash);
@@ -236,7 +233,7 @@
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   verifyEcdsaSignature(KeySecret key, bool authorityKey, GpioState gpioState,
                        Core::Ecc256::Signature::const_span signature);
 
@@ -246,7 +243,7 @@
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   authenticateEcdsaPublicKey(KeySecret key,
                              Core::Ecc256::Signature::const_span cert,
                              Core::span<const uint_least8_t> certCustomization);
@@ -262,7 +259,7 @@
   /// 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   authenticateEcdsaPublicKey(KeySecret key, bool authWrites,
                              Core::Ecc256::Signature::const_span cert,
                              Core::span<const uint_least8_t> certCustomization,
@@ -274,7 +271,7 @@
   /// 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   authenticatedEcdsaWriteMemory(int pageNum, bool useKeyS,
                                 Page::const_span newPageData,
                                 Core::Ecc256::Signature::const_span signature);
@@ -286,7 +283,7 @@
   /// @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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   authenticatedEcdsaWriteMemory(int pageNum, bool useKeyS,
                                 Page::const_span newPageData,
                                 Core::Ecc256::Signature::const_span signature,
@@ -298,7 +295,7 @@
   /// 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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   authenticatedSha256WriteMemory(int pageNum, bool useSecretS,
                                  Page::const_span newPageData,
                                  Page::const_span hmac);
@@ -310,9 +307,11 @@
   /// @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);
+  MaximInterfaceDevices_EXPORT Core::Result<void>
+  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.
@@ -320,61 +319,71 @@
   /// @param destinationSecret
   /// Destination secret to receive the computation result.
   /// @param partialSecret Partial secret to use in computation.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   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);
+  MaximInterfaceDevices_EXPORT Core::Result<void>
+  readRng(Core::span<uint_least8_t> data) const;
 
   /// Run entropy health test on the RNG.
-  MaximInterfaceDevices_EXPORT Core::error_code entropyHealthTest();
+  MaximInterfaceDevices_EXPORT Core::Result<void> entropyHealthTest() const;
 
   MaximInterfaceDevices_EXPORT static const Core::error_category &
   errorCategory();
 
 protected:
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<Core::span<uint_least8_t> >
   runCommand(Core::span<const uint_least8_t> request, int delayTime,
-             Core::span<uint_least8_t> & response);
+             Core::span<uint_least8_t> response) const;
 
-  MaximInterfaceDevices_EXPORT Core::error_code
-  runCommand(Core::span<const uint_least8_t> request, int delayTime);
+  MaximInterfaceDevices_EXPORT Core::Result<void>
+  runCommand(Core::span<const uint_least8_t> request, int delayTime) const;
 
 private:
   enum HashType { HashInput, DataInput, THASH };
 
-  Core::error_code
+  Core::Result<void>
   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(
+  Core::Result<void> 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(
+  Core::Result<void> authenticatedEcdsaWriteMemory(
       int pageNum, bool useKeyS, Page::const_span newPageData,
       Core::Ecc256::Signature::const_span signature,
       const EncryptionChallenge::const_span * challenge);
 
-  Core::error_code authenticatedSha256WriteMemory(
+  Core::Result<void> authenticatedSha256WriteMemory(
       int pageNum, bool useSecretS, Page::const_span newPageData,
       Page::const_span hmac, const EncryptionChallenge::const_span * challenge);
 
   Core::RunCommand doRunCommand;
 };
 
+} // namespace MaximInterfaceDevices
+namespace MaximInterfaceCore {
+
+template <>
+struct is_error_code_enum<MaximInterfaceDevices::DS28E83_DS28E84::ErrorValue>
+    : true_type {};
+
+} // namespace MaximInterfaceCore
+namespace MaximInterfaceDevices {
+
 inline Core::error_code make_error_code(DS28E83_DS28E84::ErrorValue e) {
   return Core::error_code(e, DS28E83_DS28E84::errorCategory());
 }
@@ -402,16 +411,16 @@
   static const int memoryPages = 107;
   static const int protectionBlocks = 24;
 
-  enum StateOperation { Backup, Restore };
+  enum StateOperation { Restore, Backup };
 
   explicit DS28E84(const Core::RunCommand & runCommand)
       : DS28E83_DS28E84(runCommand) {}
 
   /// Decrement the decrement-only counter.
-  MaximInterfaceDevices_EXPORT Core::error_code decrementCounter();
+  MaximInterfaceDevices_EXPORT Core::Result<void> decrementCounter();
 
   /// Back up or restore the state of the device to non-volatile memory.
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   deviceStateControl(StateOperation operation);
 };
 
@@ -419,20 +428,10 @@
 /// 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
+MaximInterfaceDevices_EXPORT Core::Result<void>
 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:
@@ -552,13 +551,11 @@
   /// @}
 
 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;
+  static const size_t romIdIdx = 0;
+  static const size_t pageIdx = romIdIdx + Core::RomId::size;
+  static const size_t challengeIdx = pageIdx + Page::size;
+  static const size_t pageNumIdx = challengeIdx + Page::size;
+  static const size_t manIdIdx = pageNumIdx + 1;
 
   Result::array result_;
 };
@@ -866,13 +863,11 @@
   /// @}
 
 private:
-  typedef Result::span::index_type index;
-
-  static const index encryptionChallengeIdx = 0;
-  static const index romIdIdx =
+  static const size_t encryptionChallengeIdx = 0;
+  static const size_t romIdIdx =
       encryptionChallengeIdx + EncryptionChallenge::size;
-  static const index pageNumIdx = romIdIdx + Core::RomId::size;
-  static const index manIdIdx = pageNumIdx + 1;
+  static const size_t pageNumIdx = romIdIdx + Core::RomId::size;
+  static const size_t manIdIdx = pageNumIdx + 1;
 
   Result::array result_;
 };
--- a/MaximInterfaceDevices/DS9400.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS9400.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -32,58 +32,46 @@
 
 #include "DS9400.hpp"
 
+#define TRY MaximInterfaceCore_TRY
+#define TRY_VALUE MaximInterfaceCore_TRY_VALUE
+
 namespace MaximInterfaceDevices {
 
 using namespace Core;
 
-error_code DS9400::waitAwake() {
-  error_code result;
+Result<void> DS9400::waitAwake() {
   uint_least8_t data;
   do {
-    result = uart->readByte(data);
-  } while (!result && data != 0xA5);
-  return result;
+    TRY_VALUE(data, uart->readByte());
+  } while (data != 0xA5);
+  return none;
 }
 
-error_code DS9400::start() { return uart->writeByte('S'); }
+Result<void> 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;
+Result<void> DS9400::start(uint_least8_t address) {
+  TRY(start());
+  TRY(writeByte(address));
+  return none;
 }
 
-error_code DS9400::stop() { return uart->writeByte('P'); }
+Result<void> DS9400::stop() { return uart->writeByte('P'); }
 
-error_code DS9400::writeByte(uint_least8_t data) {
+Result<void> 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;
+  TRY(uart->clearReadBuffer());
+  TRY(uart->writeBlock(packet));
+  TRY_VALUE(data, uart->readByte());
+  return (data == 0) ? makeResult(none) : I2CMaster::NackError;
 }
 
-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;
+Result<uint_least8_t> DS9400::readByte(DoAck doAck) {
+  TRY(uart->clearReadBuffer());
+  TRY(uart->writeByte(doAck == Ack ? 'R' : 'N'));
+  return uart->readByte();
 }
 
-error_code DS9400::configure(uint_least8_t config) {
+Result<void> DS9400::configure(uint_least8_t config) {
   const uint_least8_t packet[] = {'C', config};
   return uart->writeBlock(packet);
 }
--- a/MaximInterfaceDevices/DS9400.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS9400.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceDevices_DS9400
-#define MaximInterfaceDevices_DS9400
+#ifndef MaximInterfaceDevices_DS9400_hpp
+#define MaximInterfaceDevices_DS9400_hpp
 
 #include <MaximInterfaceCore/I2CMaster.hpp>
 #include <MaximInterfaceCore/Uart.hpp>
@@ -45,23 +45,24 @@
 
   void setUart(Core::Uart & uart) { this->uart = &uart; }
 
-  MaximInterfaceDevices_EXPORT Core::error_code waitAwake();
+  MaximInterfaceDevices_EXPORT Core::Result<void> waitAwake();
 
-  MaximInterfaceDevices_EXPORT Core::error_code start();
+  MaximInterfaceDevices_EXPORT Core::Result<void> start();
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  MaximInterfaceDevices_EXPORT virtual Core::Result<void>
   start(uint_least8_t address);
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code stop();
+  MaximInterfaceDevices_EXPORT virtual Core::Result<void> stop();
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
+  MaximInterfaceDevices_EXPORT virtual Core::Result<void>
   writeByte(uint_least8_t data);
 
-  MaximInterfaceDevices_EXPORT virtual Core::error_code
-  readByte(AckStatus status, uint_least8_t & data);
+  MaximInterfaceDevices_EXPORT virtual Core::Result<uint_least8_t>
+  readByte(DoAck doAck);
 
 protected:
-  MaximInterfaceDevices_EXPORT Core::error_code configure(uint_least8_t config);
+  MaximInterfaceDevices_EXPORT Core::Result<void>
+  configure(uint_least8_t config);
 
 private:
   Core::Uart * uart;
--- a/MaximInterfaceDevices/DS9481P_300.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS9481P_300.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -33,6 +33,8 @@
 #include <MaximInterfaceCore/Error.hpp>
 #include "DS9481P_300.hpp"
 
+#define TRY MaximInterfaceCore_TRY
+
 namespace MaximInterfaceDevices {
 
 using namespace Core;
@@ -41,209 +43,149 @@
     : 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<void> DS9481P_300::connect(const std::string & portName) {
+  Result<void> result = serialPort->connect(portName);
+  if (result) {
     result = selectOneWire();
     if (result) {
-      serialPort->disconnect();
+      currentBus = OneWire;
     } 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;
+      serialPort->disconnect();
     }
   }
   return result;
 }
 
-error_code DS9481P_300::OneWireMaster::reset() {
-  error_code result = parent->selectBus(OneWire);
-  if (!result) {
-    result = OneWireMasterDecorator::reset();
-  }
-  return result;
+Result<void> DS9481P_300::disconnect() { return serialPort->disconnect(); }
+
+Result<void> DS9481P_300::selectOneWire() {
+  // Escape DS9400 mode.
+  TRY(ds9400.escape());
+  TRY(ds2480b.initialize());
+  return none;
 }
 
-error_code DS9481P_300::OneWireMaster::touchBitSetLevel(bool & sendRecvBit,
-                                                        Level afterLevel) {
-  error_code result = parent->selectBus(OneWire);
-  if (!result) {
-    result = OneWireMasterDecorator::touchBitSetLevel(sendRecvBit, afterLevel);
+Result<void> DS9481P_300::selectBus(Bus newBus) {
+  if (currentBus != newBus) {
+    switch (currentBus) {
+    case OneWire: // Next bus I2C.
+      // Escape DS2480 Mode.
+      TRY(ds2480b.escape());
+      // Wait for awake notification.
+      TRY(ds9400.waitAwake());
+      break;
+
+    case I2C: // Next bus OneWire.
+      TRY(selectOneWire());
+      break;
+    }
+    currentBus = newBus;
   }
-  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;
+  return none;
 }
 
-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;
+Result<void> DS9481P_300::OneWireMaster::reset() {
+  TRY(parent->selectBus(OneWire));
+  return OneWireMasterDecorator::reset();
 }
 
-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;
+Result<bool> DS9481P_300::OneWireMaster::touchBitSetLevel(bool sendBit,
+                                                          Level afterLevel) {
+  TRY(parent->selectBus(OneWire));
+  return OneWireMasterDecorator::touchBitSetLevel(sendBit, afterLevel);
 }
 
-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;
+Result<void>
+DS9481P_300::OneWireMaster::writeByteSetLevel(uint_least8_t sendByte,
+                                              Level afterLevel) {
+  TRY(parent->selectBus(OneWire));
+  return OneWireMasterDecorator::writeByteSetLevel(sendByte, afterLevel);
 }
 
-error_code DS9481P_300::OneWireMaster::setSpeed(Speed newSpeed) {
-  error_code result = parent->selectBus(OneWire);
-  if (!result) {
-    result = OneWireMasterDecorator::setSpeed(newSpeed);
-  }
-  return result;
+Result<uint_least8_t>
+DS9481P_300::OneWireMaster::readByteSetLevel(Level afterLevel) {
+  TRY(parent->selectBus(OneWire));
+  return OneWireMasterDecorator::readByteSetLevel(afterLevel);
 }
 
-error_code DS9481P_300::OneWireMaster::setLevel(Level newLevel) {
-  error_code result = parent->selectBus(OneWire);
-  if (!result) {
-    result = OneWireMasterDecorator::setLevel(newLevel);
-  }
-  return result;
+Result<void>
+DS9481P_300::OneWireMaster::writeBlock(span<const uint_least8_t> sendBuf) {
+  TRY(parent->selectBus(OneWire));
+  return OneWireMasterDecorator::writeBlock(sendBuf);
+}
+
+Result<void>
+DS9481P_300::OneWireMaster::readBlock(span<uint_least8_t> recvBuf) {
+  TRY(parent->selectBus(OneWire));
+  return OneWireMasterDecorator::readBlock(recvBuf);
 }
 
-error_code DS9481P_300::OneWireMaster::triplet(TripletData & data) {
-  error_code result = parent->selectBus(OneWire);
-  if (!result) {
-    result = OneWireMasterDecorator::triplet(data);
-  }
-  return result;
+Result<void> DS9481P_300::OneWireMaster::setSpeed(Speed newSpeed) {
+  TRY(parent->selectBus(OneWire));
+  return OneWireMasterDecorator::setSpeed(newSpeed);
 }
 
-error_code DS9481P_300::I2CMaster::start(uint_least8_t address) {
-  error_code result = parent->selectBus(I2C);
-  if (!result) {
-    result = I2CMasterDecorator::start(address);
-  }
-  return result;
+Result<void> DS9481P_300::OneWireMaster::setLevel(Level newLevel) {
+  TRY(parent->selectBus(OneWire));
+  return OneWireMasterDecorator::setLevel(newLevel);
 }
 
-error_code DS9481P_300::I2CMaster::stop() {
-  error_code result = parent->selectBus(I2C);
-  if (!result) {
-    result = I2CMasterDecorator::stop();
-  }
-  return result;
+Result<OneWireMaster::TripletData>
+DS9481P_300::OneWireMaster::triplet(bool sendBit) {
+  TRY(parent->selectBus(OneWire));
+  return OneWireMasterDecorator::triplet(sendBit);
 }
 
-error_code DS9481P_300::I2CMaster::writeByte(uint_least8_t data) {
-  error_code result = parent->selectBus(I2C);
-  if (!result) {
-    result = I2CMasterDecorator::writeByte(data);
-  }
-  return result;
+Result<void> DS9481P_300::I2CMaster::start(uint_least8_t address) {
+  TRY(parent->selectBus(I2C));
+  return I2CMasterDecorator::start(address);
 }
 
-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;
+Result<void> DS9481P_300::I2CMaster::stop() {
+  TRY(parent->selectBus(I2C));
+  return I2CMasterDecorator::stop();
+}
+
+Result<void> DS9481P_300::I2CMaster::writeByte(uint_least8_t data) {
+  TRY(parent->selectBus(I2C));
+  return I2CMasterDecorator::writeByte(data);
 }
 
-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;
+Result<void>
+DS9481P_300::I2CMaster::writeBlock(span<const uint_least8_t> data) {
+  TRY(parent->selectBus(I2C));
+  return I2CMasterDecorator::writeBlock(data);
 }
 
-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;
+Result<void> DS9481P_300::I2CMaster::writePacket(uint_least8_t address,
+                                                 span<const uint_least8_t> data,
+                                                 DoStop doStop) {
+  TRY(parent->selectBus(I2C));
+  return I2CMasterDecorator::writePacket(address, data, doStop);
 }
 
-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;
+Result<uint_least8_t> DS9481P_300::I2CMaster::readByte(DoAck doAck) {
+  TRY(parent->selectBus(I2C));
+  return I2CMasterDecorator::readByte(doAck);
 }
 
-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;
+Result<void> DS9481P_300::I2CMaster::readBlock(span<uint_least8_t> data,
+                                               DoAck doAck) {
+  TRY(parent->selectBus(I2C));
+  return I2CMasterDecorator::readBlock(data, doAck);
 }
 
-error_code DS9481P_300::DS2480BWithEscape::escape() {
+Result<void> DS9481P_300::I2CMaster::readPacket(uint_least8_t address,
+                                                span<uint_least8_t> data,
+                                                DoStop doStop) {
+  TRY(parent->selectBus(I2C));
+  return I2CMasterDecorator::readPacket(address, data, doStop);
+}
+
+Result<void> DS9481P_300::DS2480BWithEscape::escape() {
   return sendCommand(0xE5);
 }
 
-error_code DS9481P_300::DS9400WithEscape::escape() { return configure('O'); }
+Result<void> DS9481P_300::DS9400WithEscape::escape() { return configure('O'); }
 
 } // namespace MaximInterfaceDevices
--- a/MaximInterfaceDevices/DS9481P_300.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceDevices/DS9481P_300.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceDevices_DS9481P_300
-#define MaximInterfaceDevices_DS9481P_300
+#ifndef MaximInterfaceDevices_DS9481P_300_hpp
+#define MaximInterfaceDevices_DS9481P_300_hpp
 
 #include <MaximInterfaceCore/I2CMasterDecorator.hpp>
 #include <MaximInterfaceCore/OneWireMasterDecorator.hpp>
@@ -57,14 +57,10 @@
     ds9400.setUart(serialPort);
   }
 
-  MaximInterfaceDevices_EXPORT Core::error_code
+  MaximInterfaceDevices_EXPORT Core::Result<void>
   connect(const std::string & portName);
 
-  MaximInterfaceDevices_EXPORT Core::error_code disconnect();
-
-  MaximInterfaceDevices_EXPORT bool connected() const;
-
-  MaximInterfaceDevices_EXPORT std::string portName() const;
+  MaximInterfaceDevices_EXPORT Core::Result<void> disconnect();
 
   /// Access the 1-Wire master when connected to an adapter.
   Core::OneWireMaster & oneWireMaster() { return oneWireMaster_; }
@@ -78,31 +74,31 @@
     explicit OneWireMaster(DS9481P_300 & parent)
         : OneWireMasterDecorator(parent.ds2480b), parent(&parent) {}
 
-    MaximInterfaceDevices_EXPORT virtual Core::error_code reset();
+    MaximInterfaceDevices_EXPORT virtual Core::Result<void> reset();
 
-    MaximInterfaceDevices_EXPORT virtual Core::error_code
-    touchBitSetLevel(bool & sendRecvBit, Level afterLevel);
+    MaximInterfaceDevices_EXPORT virtual Core::Result<bool>
+    touchBitSetLevel(bool sendBit, Level afterLevel);
 
-    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    MaximInterfaceDevices_EXPORT virtual Core::Result<void>
     writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
 
-    MaximInterfaceDevices_EXPORT virtual Core::error_code
-    readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
+    MaximInterfaceDevices_EXPORT virtual Core::Result<uint_least8_t>
+    readByteSetLevel(Level afterLevel);
 
-    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    MaximInterfaceDevices_EXPORT virtual Core::Result<void>
     writeBlock(Core::span<const uint_least8_t> sendBuf);
 
-    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    MaximInterfaceDevices_EXPORT virtual Core::Result<void>
     readBlock(Core::span<uint_least8_t> recvBuf);
 
-    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    MaximInterfaceDevices_EXPORT virtual Core::Result<void>
     setSpeed(Speed newSpeed);
 
-    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    MaximInterfaceDevices_EXPORT virtual Core::Result<void>
     setLevel(Level newLevel);
 
-    MaximInterfaceDevices_EXPORT virtual Core::error_code
-    triplet(TripletData & data);
+    MaximInterfaceDevices_EXPORT virtual Core::Result<TripletData>
+    triplet(bool sendBit);
 
   private:
     DS9481P_300 * parent;
@@ -113,31 +109,30 @@
     explicit I2CMaster(DS9481P_300 & parent)
         : I2CMasterDecorator(parent.ds9400), parent(&parent) {}
 
-    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    MaximInterfaceDevices_EXPORT virtual Core::Result<void>
     start(uint_least8_t address);
 
-    MaximInterfaceDevices_EXPORT virtual Core::error_code stop();
+    MaximInterfaceDevices_EXPORT virtual Core::Result<void> stop();
 
-    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    MaximInterfaceDevices_EXPORT virtual Core::Result<void>
     writeByte(uint_least8_t data);
 
-    MaximInterfaceDevices_EXPORT virtual Core::error_code
+    MaximInterfaceDevices_EXPORT virtual Core::Result<void>
     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::Result<void>
+    writePacket(uint_least8_t address, Core::span<const uint_least8_t> data,
+                DoStop doStop);
 
-    MaximInterfaceDevices_EXPORT virtual Core::error_code
-    readBlock(AckStatus status, Core::span<uint_least8_t> data);
+    MaximInterfaceDevices_EXPORT virtual Core::Result<uint_least8_t>
+    readByte(DoAck doAck);
 
-  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::Result<void>
+    readBlock(Core::span<uint_least8_t> data, DoAck doAck);
 
-    MaximInterfaceDevices_EXPORT virtual Core::error_code
-    doReadPacket(uint_least8_t address, Core::span<uint_least8_t> data,
-                 bool sendStop);
+    MaximInterfaceDevices_EXPORT virtual Core::Result<void>
+    readPacket(uint_least8_t address, Core::span<uint_least8_t> data,
+               DoStop doStop);
 
   private:
     DS9481P_300 * parent;
@@ -148,14 +143,14 @@
     DS2480BWithEscape(Core::Sleep & sleep, Core::Uart & uart)
         : DS2480B(sleep, uart) {}
 
-    Core::error_code escape();
+    Core::Result<void> escape();
   };
 
   class DS9400WithEscape : public DS9400 {
   public:
     explicit DS9400WithEscape(Core::Uart & uart) : DS9400(uart) {}
 
-    Core::error_code escape();
+    Core::Result<void> escape();
   };
 
   enum Bus { OneWire, I2C };
@@ -167,8 +162,8 @@
   DS9400WithEscape ds9400;
   I2CMaster i2cMaster_;
 
-  Core::error_code selectOneWire();
-  Core::error_code selectBus(Bus newBus);
+  Core::Result<void> selectOneWire();
+  Core::Result<void> selectBus(Bus newBus);
 
   friend class OneWireMaster;
   friend class I2CMaster;
--- a/MaximInterfaceMbed/I2CMaster.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceMbed/I2CMaster.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -36,40 +36,49 @@
 
 using namespace MaximInterfaceCore;
 
-error_code I2CMaster::start(uint_least8_t address) {
+Result<void> I2CMaster::start(uint_least8_t address) {
   i2c->start();
   return writeByte(address);
 }
 
-error_code I2CMaster::stop() {
+Result<void> I2CMaster::stop() {
   i2c->stop();
-  return error_code();
+  return none;
 }
 
-error_code I2CMaster::writeByte(uint_least8_t data) {
-  return (i2c->write(data) == 1) ? error_code() : make_error_code(NackError);
+Result<void> I2CMaster::writeByte(uint_least8_t data) {
+  return (i2c->write(data) == 1) ? makeResult(none) : NackError;
 }
 
-error_code I2CMaster::doWritePacket(uint_least8_t address,
+Result<void> I2CMaster::writePacket(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);
+                                    DoStop doStop) {
+  const Result<void> result =
+      (i2c->write(address, reinterpret_cast<const char *>(data.data()),
+                  data.size(), doStop != Stop) == 0)
+          ? makeResult(none)
+          : NackError;
+  if (doStop == StopOnError && !result) {
+    i2c->stop();
+  }
+  return result;
 }
 
-error_code I2CMaster::readByte(AckStatus status, uint_least8_t & data) {
-  data = i2c->read(status == Ack);
-  return error_code();
+Result<uint_least8_t> I2CMaster::readByte(DoAck doAck) {
+  return i2c->read(doAck == Ack);
 }
 
-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);
+Result<void> I2CMaster::readPacket(uint_least8_t address,
+                                   span<uint_least8_t> data, DoStop doStop) {
+  const Result<void> result =
+      (i2c->read(address, reinterpret_cast<char *>(data.data()), data.size(),
+                 doStop != Stop) == 0)
+          ? makeResult(none)
+          : NackError;
+  if (doStop == StopOnError && !result) {
+    i2c->stop();
+  }
+  return result;
 }
 
 } // namespace MaximInterfaceMbed
--- a/MaximInterfaceMbed/I2CMaster.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceMbed/I2CMaster.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceMbed_I2CMaster
-#define MaximInterfaceMbed_I2CMaster
+#ifndef MaximInterfaceMbed_I2CMaster_hpp
+#define MaximInterfaceMbed_I2CMaster_hpp
 
 #include <MaximInterfaceCore/I2CMaster.hpp>
 #include <mbed-os/drivers/I2C.h>
@@ -45,24 +45,22 @@
 
   void setI2C(mbed::I2C & i2c) { this->i2c = &i2c; }
 
-  virtual MaximInterfaceCore::error_code start(uint_least8_t address);
-
-  virtual MaximInterfaceCore::error_code stop();
+  virtual MaximInterfaceCore::Result<void> start(uint_least8_t address);
 
-  virtual MaximInterfaceCore::error_code writeByte(uint_least8_t data);
+  virtual MaximInterfaceCore::Result<void> stop();
 
-  virtual MaximInterfaceCore::error_code readByte(AckStatus status,
-                                                  uint_least8_t & data);
+  virtual MaximInterfaceCore::Result<void> writeByte(uint_least8_t data);
 
-protected:
-  virtual MaximInterfaceCore::error_code
-  doReadPacket(uint_least8_t address,
-               MaximInterfaceCore::span<uint_least8_t> data, bool sendStop);
+  virtual MaximInterfaceCore::Result<void>
+  writePacket(uint_least8_t address,
+              MaximInterfaceCore::span<const uint_least8_t> data,
+              DoStop doStop);
 
-  virtual MaximInterfaceCore::error_code
-  doWritePacket(uint_least8_t address,
-                MaximInterfaceCore::span<const uint_least8_t> data,
-                bool sendStop);
+  virtual MaximInterfaceCore::Result<uint_least8_t> readByte(DoAck doAck);
+
+  virtual MaximInterfaceCore::Result<void>
+  readPacket(uint_least8_t address,
+             MaximInterfaceCore::span<uint_least8_t> data, DoStop doStop);
 
 private:
   mbed::I2C * i2c;
--- a/MaximInterfaceMbed/Sleep.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceMbed/Sleep.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -37,11 +37,6 @@
 
 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
--- a/MaximInterfaceMbed/Sleep.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceMbed/Sleep.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,24 +30,18 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceMbed_Sleep
-#define MaximInterfaceMbed_Sleep
+#ifndef MaximInterfaceMbed_Sleep_hpp
+#define MaximInterfaceMbed_Sleep_hpp
 
 #include <MaximInterfaceCore/Sleep.hpp>
-#include <MaximInterfaceCore/Uncopyable.hpp>
 
 namespace MaximInterfaceMbed {
 
 void sleep(int ms);
 
-class Sleep : public MaximInterfaceCore::Sleep,
-              private MaximInterfaceCore::Uncopyable {
+class Sleep : public MaximInterfaceCore::Sleep {
 public:
-  static Sleep & instance();
   virtual void invoke(int ms) const;
-
-private:
-  Sleep() {}
 };
 
 } // namespace MaximInterfaceMbed
--- a/MaximInterfaceMbed/Uart.cpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceMbed/Uart.cpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -40,64 +40,61 @@
 
 static const int timeout_ms = 10000;
 
-error_code Uart::setBaudRate(int_least32_t baudRate) {
+Result<void> Uart::setBaudRate(int_least32_t baudRate) {
   serial->baud(baudRate);
-  return error_code();
+  return none;
 }
 
-error_code Uart::sendBreak() {
+Result<void> Uart::sendBreak() {
   serial->send_break();
-  return error_code();
+  return none;
 }
 
-error_code Uart::clearReadBuffer() {
+Result<void> Uart::clearReadBuffer() {
   while (serial->readable()) {
     serial->getc();
   }
-  return error_code();
+  return none;
 }
 
-error_code Uart::writeByte(uint_least8_t data) {
+Result<void> 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);
+        return HardwareError;
       }
     }
   }
   serial->putc(data);
-  return error_code();
+  return none;
 }
 
-error_code Uart::readByte(uint_least8_t & data) {
+Result<uint_least8_t> Uart::readByte() {
   if (!serial->readable()) {
     mbed::Timer timer;
     timer.start();
     while (!serial->readable()) {
       if (timer.read_ms() >= timeout_ms) {
-        return make_error_code(TimeoutError);
+        return TimeoutError;
       }
     }
   }
-  data = serial->getc();
-  return error_code();
+  return serial->getc();
 }
 
 const error_category & Uart::errorCategory() {
   static class : public error_category {
   public:
-    virtual const char * name() const { return "mbed UART"; }
+    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);
       }
+      return defaultErrorMessage(condition);
     }
   } instance;
   return instance;
--- a/MaximInterfaceMbed/Uart.hpp	Mon Jul 22 11:44:07 2019 -0500
+++ b/MaximInterfaceMbed/Uart.hpp	Mon Sep 16 11:13:37 2019 -0500
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+* Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,8 @@
 * ownership rights.
 *******************************************************************************/
 
-#ifndef MaximInterfaceMbed_Uart
-#define MaximInterfaceMbed_Uart
+#ifndef MaximInterfaceMbed_Uart_hpp
+#define MaximInterfaceMbed_Uart_hpp
 
 #include <MaximInterfaceCore/Uart.hpp>
 #include <mbed-os/drivers/Serial.h>
@@ -49,15 +49,15 @@
 
   void setSerial(mbed::Serial & serial) { this->serial = &serial; }
 
-  virtual MaximInterfaceCore::error_code setBaudRate(int_least32_t baudRate);
+  virtual MaximInterfaceCore::Result<void> setBaudRate(int_least32_t baudRate);
 
-  virtual MaximInterfaceCore::error_code sendBreak();
+  virtual MaximInterfaceCore::Result<void> sendBreak();
 
-  virtual MaximInterfaceCore::error_code clearReadBuffer();
+  virtual MaximInterfaceCore::Result<void> clearReadBuffer();
 
-  virtual MaximInterfaceCore::error_code writeByte(uint_least8_t data);
+  virtual MaximInterfaceCore::Result<void> writeByte(uint_least8_t data);
 
-  virtual MaximInterfaceCore::error_code readByte(uint_least8_t & data);
+  virtual MaximInterfaceCore::Result<uint_least8_t> readByte();
 
   static const MaximInterfaceCore::error_category & errorCategory();
 
@@ -65,6 +65,15 @@
   mbed::Serial * serial;
 };
 
+} // namespace MaximInterfaceMbed
+namespace MaximInterfaceCore {
+
+template <>
+struct is_error_code_enum<MaximInterfaceMbed::Uart::ErrorValue> : true_type {};
+
+} // namespace MaximInterfaceCore
+namespace MaximInterfaceMbed {
+
 inline MaximInterfaceCore::error_code make_error_code(Uart::ErrorValue e) {
   return MaximInterfaceCore::error_code(e, Uart::errorCategory());
 }
--- a/mbed_lib.json	Mon Jul 22 11:44:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-{
-  "name": "MaximInterface",
-  "macros": ["__STDC_LIMIT_MACROS"]
-}
\ No newline at end of file