Extended MaximInterface

Dependents:   mbed_DS28EC20_GPIO

Files at this revision

API Documentation at this revision

Comitter:
IanBenzMaxim
Date:
Mon Mar 04 08:10:00 2019 -0600
Parent:
6:a8c83a2e6fa4
Child:
8:211d1b8f730c
Commit message:
Updated to version 1.7.

Changed in this revision

Devices/DS18B20.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS1920.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS2413.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS2431.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS2431.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS2465.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS2465.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS2482_DS2484.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS2482_DS2484.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS28C36_DS2476.cpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS28C36_DS2476.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS28E15_22_25.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS28E17.hpp Show annotated file Show diff for this revision Revisions of this file
Devices/DS28E38.hpp Show annotated file Show diff for this revision Revisions of this file
Links/I2CMaster.hpp Show annotated file Show diff for this revision Revisions of this file
Links/OneWireMaster.hpp Show annotated file Show diff for this revision Revisions of this file
Links/RomCommands.hpp Show annotated file Show diff for this revision Revisions of this file
Links/SelectRom.hpp Show annotated file Show diff for this revision Revisions of this file
Links/SerialPort.hpp Show annotated file Show diff for this revision Revisions of this file
Links/Uart.hpp Show annotated file Show diff for this revision Revisions of this file
Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/owlink.h Show annotated file Show diff for this revision Revisions of this file
Utilities/ChangeSizeType.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/Ecc256.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/Error.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/FlagSet.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/Function.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/RomId.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/SafeBool.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/Segment.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/Sha256.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/array.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/array_span.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/crc.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/optional.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/span.hpp Show annotated file Show diff for this revision Revisions of this file
Utilities/system_error.hpp Show annotated file Show diff for this revision Revisions of this file
--- a/Devices/DS18B20.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Devices/DS18B20.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -40,7 +40,7 @@
 
 namespace MaximInterface {
 
-/// DS18B20 Programmable Resolution 1-Wire Digital Thermometer
+/// @brief DS18B20 Programmable Resolution 1-Wire Digital Thermometer
 /// @details The DS18B20 digital thermometer provides 9-bit to 12-bit
 /// Celsius temperature measurements and has an alarm function with
 /// nonvolatile user-programmable upper and lower trigger points. The
@@ -125,6 +125,7 @@
 };
 
 /// Reads the current temperature as an integer value with decimal.
+/// @param ds18b20 Device to read.
 /// @param[out] temperature Temperature in degrees Celsius multiplied by 16.
 MaximInterface_EXPORT error_code readTemperature(DS18B20 & ds18b20,
                                                  int & temperature);
--- a/Devices/DS1920.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Devices/DS1920.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -40,7 +40,7 @@
 
 namespace MaximInterface {
 
-/// DS1920 1-Wire Temperature iButton
+/// @brief DS1920 1-Wire Temperature iButton
 /// @details The iButton® temperature logger (DS1920) provides
 /// direct-to-digital 9-bit temperature readings over a range of
 /// -55°C to +100°C in 0.5° increments. The iButton communicates with
@@ -68,7 +68,7 @@
     this->selectRom = selectRom;
   }
 
-  /// Write Scratchpad Command
+  /// @brief Write Scratchpad Command
   /// @details If the result of a temperature measurement is higher
   /// than TH or lower than TL, an alarm flag inside the device is
   /// set. This flag is updated with every temperature measurement.
@@ -79,21 +79,21 @@
   MaximInterface_EXPORT error_code writeScratchpad(uint_least8_t th,
                                                    uint_least8_t tl);
 
-  /// Read Scratchpad Command
+  /// @brief Read Scratchpad Command
   /// @param[out] scratchpad Contents of scratchpad.
   MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span scratchpad);
 
-  /// Copy Scratchpad Command
+  /// @brief Copy Scratchpad Command
   /// @details This command copies from the scratchpad into the
   /// EEPROM of the DS1920, storing the temperature trigger bytes
   /// in nonvolatile memory.
   MaximInterface_EXPORT error_code copyScratchpad();
 
-  /// Convert Temperature Command
+  /// @brief Convert Temperature Command
   /// @details This command begins a temperature conversion.
   MaximInterface_EXPORT error_code convertTemperature();
 
-  /// Recall Command
+  /// @brief Recall Command
   /// @details This command recalls the temperature trigger values
   /// stored in EEPROM to the scratchpad.
   MaximInterface_EXPORT error_code recallEeprom();
@@ -106,7 +106,8 @@
   const Sleep * sleep;
 };
 
-/// Reads the current temperature as an integer value.
+/// @brief Reads the current temperature as an integer value.
+/// @param ds1920 Device to read.
 /// @param[out] temperature Temperature in degrees Celsius multiplied by 2.
 MaximInterface_EXPORT error_code readTemperature(DS1920 & ds1920,
                                                  int & temperature);
--- a/Devices/DS2413.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Devices/DS2413.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -40,7 +40,7 @@
 
 namespace MaximInterface {
 
-/// DS2413 1-Wire Dual Channel Addressable Switch
+/// @brief DS2413 1-Wire Dual Channel Addressable Switch
 /// @details The DS2413 is a dual-channel programmable I/O 1-Wire®
 /// chip. The PIO outputs are configured as open-drain and provide up
 /// to 20mA continuous sink capability and off-state operating voltage
@@ -88,14 +88,13 @@
   OneWireMaster * master;
 };
 
-/// @{
-/// Write the output logic state for only a single PIO pin.
+/// Write the output logic state for only PIOA.
 MaximInterface_EXPORT error_code writePioAOutputState(DS2413 & ds2413,
                                                       bool pioAState);
-                                                      
+
+/// Write the output logic state for only PIOB.
 MaximInterface_EXPORT error_code writePioBOutputState(DS2413 & ds2413,
                                                       bool pioBState);
-/// @}
 
 inline error_code make_error_code(DS2413::ErrorValue e) {
   return error_code(e, DS2413::errorCategory());
--- a/Devices/DS2431.cpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Devices/DS2431.cpp	Mon Mar 04 08:10:00 2019 -0600
@@ -55,59 +55,59 @@
 
 error_code DS2431::readMemory(Address beginAddress,
                               span<uint_least8_t> data) const {  
-  error_code owmResult = selectRom(*master);
-  if (owmResult) {
-    return owmResult;
+  error_code result = selectRom(*master);
+  if (result) {
+    return result;
   }
   const uint_least8_t sendBlock[] = {0xF0, beginAddress, 0x00};
-  owmResult = master->writeBlock(sendBlock);
-  if (owmResult) {
-    return owmResult;
+  result = master->writeBlock(sendBlock);
+  if (result) {
+    return result;
   }
-  owmResult = master->readBlock(data);
-  return owmResult;
+  result = master->readBlock(data);
+  return result;
 }
 
 error_code DS2431::writeScratchpad(Address targetAddress,
                                    Scratchpad::const_span data) {  
-  error_code owmResult = selectRom(*master);
-  if (owmResult) {
-    return owmResult;
+  error_code result = selectRom(*master);
+  if (result) {
+    return result;
   }
   uint_least8_t block[3 + Scratchpad::size] = {0x0F, targetAddress, 0x00};
   std::copy(data.begin(), data.end(), block + 3);
-  owmResult = master->writeBlock(block);
-  if (owmResult) {
-    return owmResult;
+  result = master->writeBlock(block);
+  if (result) {
+    return result;
   }
   const uint_fast16_t calculatedCrc = calculateCrc16(block) ^ 0xFFFFU;
-  owmResult = master->readBlock(make_span(block, 2));
-  if (owmResult) {
-    return owmResult;
+  result = master->readBlock(make_span(block, 2));
+  if (result) {
+    return result;
   }
   if (calculatedCrc !=
       ((static_cast<uint_fast16_t>(block[1]) << 8) | block[0])) {
-    owmResult = make_error_code(CrcError);
+    result = make_error_code(CrcError);
   }
-  return owmResult;
+  return result;
 }
 
 error_code DS2431::readScratchpad(Scratchpad::span data,
                                   uint_least8_t & esByte) {
   typedef array<uint_least8_t, 6 + Scratchpad::size> Block;
 
-  error_code owmResult = selectRom(*master);
-  if (owmResult) {
-    return owmResult;
+  error_code result = selectRom(*master);
+  if (result) {
+    return result;
   }
   Block block = {0xAA};
-  owmResult = master->writeByte(block.front());
-  if (owmResult) {
-    return owmResult;
+  result = master->writeByte(block.front());
+  if (result) {
+    return result;
   }
-  owmResult = master->readBlock(make_span(block.data() + 1, block.size() - 1));
-  if (owmResult) {
-    return owmResult;
+  result = master->readBlock(make_span(block).subspan(1));
+  if (result) {
+    return result;
   }
   Block::const_iterator blockIt = block.end();
   uint_fast16_t receivedCrc = static_cast<uint_fast16_t>(*(--blockIt)) << 8;
@@ -120,38 +120,38 @@
     std::copy(blockIt, blockItEnd, data.begin());
     esByte = *(--blockIt);
   } else {
-    owmResult = make_error_code(CrcError);
+    result = make_error_code(CrcError);
   }
-  return owmResult;
+  return result;
 }
 
 error_code DS2431::copyScratchpad(Address targetAddress, uint_least8_t esByte) {  
-  error_code owmResult = selectRom(*master);
-  if (owmResult) {
-    return owmResult;
+  error_code result = selectRom(*master);
+  if (result) {
+    return result;
   }
   uint_least8_t block[] = {0x55, targetAddress, 0x00};
-  owmResult = master->writeBlock(block);
-  if (owmResult) {
-    return owmResult;
+  result = master->writeBlock(block);
+  if (result) {
+    return result;
   }
-  owmResult = master->writeByteSetLevel(esByte, OneWireMaster::StrongLevel);
-  if (owmResult) {
-    return owmResult;
+  result = master->writeByteSetLevel(esByte, OneWireMaster::StrongLevel);
+  if (result) {
+    return result;
   }
   sleep->invoke(10);
-  owmResult = master->setLevel(OneWireMaster::NormalLevel);
-  if (owmResult) {
-    return owmResult;
+  result = master->setLevel(OneWireMaster::NormalLevel);
+  if (result) {
+    return result;
   }
-  owmResult = master->readByte(block[0]);
-  if (owmResult) {
-    return owmResult;
+  result = master->readByte(block[0]);
+  if (result) {
+    return result;
   }
   if (block[0] != 0xAA) {
-    owmResult = make_error_code(OperationFailure);
+    result = make_error_code(OperationFailure);
   }
-  return owmResult;
+  return result;
 }
 
 const error_category & DS2431::errorCategory() {
@@ -165,11 +165,9 @@
         return "CRC Error";
 
       case OperationFailure:
-        return "Operation Failure";
-
-      default:
-        return defaultErrorMessage(condition);
+        return "Operation Failure";        
       }
+      return defaultErrorMessage(condition);
     }
   } instance;
   return instance;
--- a/Devices/DS2431.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Devices/DS2431.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -40,7 +40,7 @@
 
 namespace MaximInterface {
 
-/// DS2431 1024-bit 1-Wire EEPROM
+/// @brief DS2431 1024-bit 1-Wire EEPROM
 /// @details The DS2431 is a 1024-bit, 1-Wire® EEPROM chip organized
 /// as four memory pages of 256 bits each. Data is written to an 8-byte
 /// scratchpad, verified, and then copied to the EEPROM memory. As a
@@ -70,26 +70,27 @@
     this->selectRom = selectRom;
   }
 
-  /// Reads block of data from EEPROM memory.
+  /// @brief Reads block of data from EEPROM memory.
   /// @param[in] beginAddress EEPROM memory address to start reading from.
   /// @param[out] data EEPROM data read from the device.
   MaximInterface_EXPORT error_code readMemory(Address beginAddress,
                                               span<uint_least8_t> data) const;
 
-  /// Writes 8 bytes to the scratchpad.
-  /// @param[in] targetAddress EEPROM memory address that this data.
-  /// will be copied to.  Must be on row boundary.
+  /// @brief Writes 8 bytes to the scratchpad.
+  /// @param[in] targetAddress
+  /// EEPROM memory address that this data will be copied to.
+  /// Must be on row boundary.
   /// @param[in] data Data to write to scratchpad.
   MaximInterface_EXPORT error_code writeScratchpad(Address targetAddress,
                                                    Scratchpad::const_span data);
 
-  /// Reads contents of scratchpad.
+  /// @brief Reads contents of scratchpad.
   /// @param[out] data Data read from scratchpad.
   /// @param[out] esByte E/S byte read before scratchpad data.
   MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span data,
                                                   uint_least8_t & esByte);
 
-  /// Copies contents of scratchpad to EEPROM.
+  /// @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.
@@ -104,8 +105,10 @@
   const Sleep * sleep;
 };
 
+/// @brief
 /// Writes data to EEPROM using Write Scratchpad, Read Scratchpad,
 /// and Copy Scratchpad commands.
+/// @param device Device to write.
 /// @param[in] targetAddress EEPROM memory address to start writing at.
 /// @param[in] data Data to write to EEPROM.
 MaximInterface_EXPORT error_code writeMemory(DS2431 & device,
--- a/Devices/DS2465.cpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Devices/DS2465.cpp	Mon Mar 04 08:10:00 2019 -0600
@@ -206,9 +206,7 @@
     return error_code();
   }
   // Set the level
-  Config newConfig = curConfig;
-  newConfig.setSPU(level == StrongLevel);
-  return writeConfig(newConfig);
+  return writeConfig(Config(curConfig).setSPU(level == StrongLevel));
 }
 
 error_code DS2465::setLevel(Level newLevel) {
@@ -229,9 +227,7 @@
     return error_code();
   }
   // Set the speed
-  Config newConfig = curConfig;
-  newConfig.set1WS(newSpeed == OverdriveSpeed);
-  return writeConfig(newConfig);
+  return writeConfig(Config(curConfig).set1WS(newSpeed == OverdriveSpeed));
 }
 
 error_code DS2465::triplet(TripletData & data) {
--- a/Devices/DS2465.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Devices/DS2465.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -47,7 +47,7 @@
 public:
   enum ErrorValue { HardwareError = 1, ArgumentOutOfRangeError };
 
-  /// 1-Wire port adjustment parameters.
+  /// @brief 1-Wire port adjustment parameters.
   /// @note See datasheet page 13.
   enum PortParameter {
     tRSTL_STD,
@@ -80,10 +80,14 @@
     explicit Config(uint_least8_t readByte = optionAPU)
         : readByte_(readByte & 0xF) {}
 
+    /// @name 1WS
+    /// @brief 1-Wire Speed
     /// @{
-    /// 1-Wire Speed
+    
+    /// Get 1WS bit.
     bool get1WS() const { return (readByte_ & option1WS) == option1WS; }
     
+    /// Set 1WS bit.
     Config & set1WS(bool new1WS) {
       if (new1WS) {
         readByte_ |= option1WS;
@@ -92,12 +96,17 @@
       }
       return *this;
     }
+    
     /// @}
 
+    /// @name SPU
+    /// @brief Strong Pullup
     /// @{
-    /// Strong Pullup
+    
+    /// Get SPU bit.
     bool getSPU() const { return (readByte_ & optionSPU) == optionSPU; }
     
+    /// Set SPU bit.
     Config & setSPU(bool newSPU) {
       if (newSPU) {
         readByte_ |= optionSPU;
@@ -106,12 +115,17 @@
       }
       return *this;
     }
+    
     /// @}
 
+    /// @name PDN
+    /// @brief 1-Wire Power Down
     /// @{
-    /// 1-Wire Power Down
+    
+    /// Get PDN bit.
     bool getPDN() const { return (readByte_ & optionPDN) == optionPDN; }
     
+    /// Set PDN bit.
     Config & setPDN(bool newPDN) {
       if (newPDN) {
         readByte_ |= optionPDN;
@@ -120,12 +134,17 @@
       }
       return *this;
     }
+    
     /// @}
 
+    /// @name APU
+    /// @brief Active Pullup
     /// @{
-    /// Active Pullup
+    
+    /// Get APU bit.
     bool getAPU() const { return (readByte_ & optionAPU) == optionAPU; }
     
+    /// Set APU bit.
     Config & setAPU(bool newAPU) {
       if (newAPU) {
         readByte_ |= optionAPU;
@@ -134,6 +153,7 @@
       }
       return *this;
     }
+    
     /// @}
 
     /// Byte representation that is read from the DS2465.
@@ -166,14 +186,14 @@
   /// Initialize hardware for use.
   MaximInterface_EXPORT error_code initialize(Config config = Config());
 
-  /// Write a new configuration to the DS2465.
+  /// @brief Write a new configuration to the DS2465.
   /// @param[in] config New configuration to write.
   MaximInterface_EXPORT error_code writeConfig(Config config);
 
-  /// Write a new port configuration parameter to the DS2465.
+  /// @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.
+  /// @param[in] val
+  /// New parameter value to set. Consult datasheet for value mappings.
   MaximInterface_EXPORT error_code writePortParameter(PortParameter param,
                                                       int val);
 
@@ -198,26 +218,31 @@
   
   MaximInterface_EXPORT virtual error_code setSpeed(Speed newSpeed);
   
-  /// @note The DS2465 only supports enabling strong pullup following a 1-Wire
-  /// read or write operation.
+  /// @copydoc OneWireMaster::setLevel
+  /// @note
+  /// The DS2465 only supports enabling strong pullup following a 1-Wire read or
+  /// write operation.
   MaximInterface_EXPORT virtual error_code setLevel(Level newLevel);
   
   MaximInterface_EXPORT virtual error_code triplet(TripletData & data);
 
   // DS2465 Coprocessor Commands
 
-  /// Read data from an EEPROM memory page.
+  /// @brief Read data from an EEPROM memory page.
   /// @param pageNum Page number to read from.
+  /// @param[out] data Data that was read.
   MaximInterface_EXPORT error_code readPage(int pageNum, Page::span data) const;
 
-  /// Write data to an EEPROM memory page.
+  /// @brief Write data to an EEPROM memory page.
   /// @param pageNum Page number to copy to.
+  /// @param data Data to write.
   MaximInterface_EXPORT error_code writePage(int pageNum,
                                              Page::const_span data);
 
-  /// Write data to an EEPROM memory segment.
+  /// @brief Write data to an EEPROM memory segment.
   /// @param pageNum Page number to copy to.
   /// @param segmentNum Segment number to copy to.
+  /// @param data Data to write.
   MaximInterface_EXPORT error_code writeSegment(int pageNum, int segmentNum,
                                                 Segment::const_span data);
 
@@ -225,12 +250,12 @@
   MaximInterface_EXPORT error_code
   writeMasterSecret(Sha256::Hash::const_span masterSecret);
 
-  /// Compute Next Master Secret.
+  /// @brief Compute Next Master Secret.
   /// @param data Combined data fields for computation.
   MaximInterface_EXPORT error_code
   computeNextMasterSecret(Sha256::AuthenticationData::const_span data);
 
-  /// Compute Next Master Secret with page swapping.
+  /// @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.
@@ -238,18 +263,18 @@
   computeNextMasterSecretWithSwap(Sha256::AuthenticationData::const_span data,
                                   int pageNum, PageRegion region);
 
-  /// Compute Write MAC.
+  /// @brief Compute Write MAC.
   /// @param data Combined data fields for computation.
   /// @param[out] mac Computed Write MAC.
   MaximInterface_EXPORT error_code computeWriteMac(
       Sha256::WriteMacData::const_span data, Sha256::Hash::span mac) const;
 
-  /// Compute Write MAC.
+  /// @brief Compute Write MAC.
   /// @param data Combined data fields for computation.
   MaximInterface_EXPORT error_code
   computeAndTransmitWriteMac(Sha256::WriteMacData::const_span data) const;
 
-  /// Compute Write MAC with page swapping.
+  /// @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.
@@ -258,19 +283,19 @@
   computeWriteMacWithSwap(Sha256::WriteMacData::const_span data, int pageNum,
                           int segmentNum, Sha256::Hash::span mac) const;
 
-  /// Compute Write MAC with page swapping.
+  /// @brief Compute Write MAC with page swapping.
   /// @param data Combined data fields for computation.
   /// @param pageNum Page number to swap in.
   /// @param segmentNum Segment number to swap in.
   MaximInterface_EXPORT error_code computeAndTransmitWriteMacWithSwap(
       Sha256::WriteMacData::const_span data, int pageNum, int segmentNum) const;
 
-  /// Compute Slave Secret (S-Secret).
+  /// @brief Compute Slave Secret (S-Secret).
   /// @param data Combined data fields for computation.
   MaximInterface_EXPORT error_code
   computeSlaveSecret(Sha256::AuthenticationData::const_span data);
 
-  /// Compute Slave Secret (S-Secret) with page swapping.
+  /// @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.
@@ -278,19 +303,19 @@
   computeSlaveSecretWithSwap(Sha256::AuthenticationData::const_span data,
                              int pageNum, PageRegion region);
 
-  /// Compute Authentication MAC.
+  /// @brief Compute Authentication MAC.
   /// @param data Combined data fields for computation.
   /// @param[out] mac Computed Auth MAC.
   MaximInterface_EXPORT error_code
   computeAuthMac(Sha256::AuthenticationData::const_span data,
                  Sha256::Hash::span mac) const;
 
-  /// Compute Authentication MAC.
+  /// @brief Compute Authentication MAC.
   /// @param data Combined data fields for computation.
   MaximInterface_EXPORT error_code
   computeAndTransmitAuthMac(Sha256::AuthenticationData::const_span data) const;
 
-  /// Compute Authentication MAC with page swapping.
+  /// @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.
@@ -299,7 +324,7 @@
       Sha256::AuthenticationData::const_span data, int pageNum,
       PageRegion region, Sha256::Hash::span mac) const;
 
-  /// Compute Authentication MAC with page swapping.
+  /// @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.
@@ -315,29 +340,31 @@
   uint_least8_t address_;
   Config curConfig;
 
-  /// Performs a soft reset on the DS2465.
+  /// @brief Performs a soft reset on the DS2465.
   /// @note This is not a 1-Wire Reset.
   error_code resetDevice();
 
-  /// Polls the DS2465 status waiting for the 1-Wire Busy bit (1WB) to be cleared.
+  /// @brief
+  /// Polls the DS2465 status waiting for the 1-Wire Busy bit (1WB) to be
+  /// cleared.
   /// @param[out] pStatus Optionally retrive the status byte when 1WB cleared.
   /// @returns Success or TimeoutError if poll limit reached.
   error_code pollBusy(uint_least8_t * pStatus = NULL) const;
 
-  /// Ensure that the desired 1-Wire level is set in the configuration.
+  /// @brief Ensure that the desired 1-Wire level is set in the configuration.
   /// @param level Desired 1-Wire level.
   error_code configureLevel(Level level);
 
-  /// Const since only for internal use.
+  /// @note Const since only for internal use.
   error_code writeMemory(uint_least8_t addr,
                          span<const uint_least8_t> buf) const;
 
-  /// Read memory from the DS2465.
+  /// @brief Read memory from the DS2465.
   /// @param addr Address to begin reading from.
   /// @param[out] buf Buffer to hold read data.
   error_code readMemory(uint_least8_t addr, span<uint_least8_t> buf) const;
 
-  /// Read memory from the DS2465 at the current pointer.
+  /// @brief Read memory from the DS2465 at the current pointer.
   /// @param[out] buf Buffer to hold read data.
   error_code readMemory(span<uint_least8_t> buf) const;
 
--- a/Devices/DS2482_DS2484.cpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Devices/DS2482_DS2484.cpp	Mon Mar 04 08:10:00 2019 -0600
@@ -222,9 +222,7 @@
     return error_code();
   }
   // Set the speed
-  Config newConfig = curConfig;
-  newConfig.set1WS(newSpeed == OverdriveSpeed);
-  return writeConfig(newConfig);
+  return writeConfig(Config(curConfig).set1WS(newSpeed == OverdriveSpeed));
 }
 
 error_code DS2482_DS2484::setLevel(Level newLevel) {
@@ -297,9 +295,7 @@
     return error_code();
   }
   // Set the level
-  Config newConfig = curConfig;
-  newConfig.setSPU(level == StrongLevel);
-  return writeConfig(newConfig);
+  return writeConfig(Config(curConfig).setSPU(level == StrongLevel));
 }
 
 error_code DS2482_DS2484::sendCommand(uint_least8_t cmd) const {
@@ -412,7 +408,7 @@
   }
 
   uint_least8_t portConfig = val + 1;
-  for (int numReads = -1; numReads < param; numReads++) {
+  for (int reads = -1; reads < param; ++reads) {
     result = readRegister(portConfig);
     if (result) {
       return result;
--- a/Devices/DS2482_DS2484.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Devices/DS2482_DS2484.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -51,10 +51,14 @@
     explicit Config(uint_least8_t readByte = optionAPU)
         : readByte_(readByte & 0xF) {}
 
+    /// @name 1WS
+    /// @brief 1-Wire Speed
     /// @{
-    /// 1-Wire Speed
+    
+    /// Get 1WS bit.
     bool get1WS() const { return (readByte_ & option1WS) == option1WS; }
     
+    /// Set 1WS bit.
     Config & set1WS(bool new1WS) {
       if (new1WS) {
         readByte_ |= option1WS;
@@ -63,12 +67,17 @@
       }
       return *this;
     }
+    
     /// @}
 
+    /// @name SPU
+    /// @brief Strong Pullup
     /// @{
-    /// Strong Pullup
+    
+    /// Get SPU bit.
     bool getSPU() const { return (readByte_ & optionSPU) == optionSPU; }
     
+    /// Set SPU bit.
     Config & setSPU(bool newSPU) {
       if (newSPU) {
         readByte_ |= optionSPU;
@@ -77,12 +86,17 @@
       }
       return *this;
     }
+    
     /// @}
 
+    /// @name PDN
+    /// @brief 1-Wire Power Down
     /// @{
-    /// 1-Wire Power Down
+    
+    /// Get PDN bit.
     bool getPDN() const { return (readByte_ & optionPDN) == optionPDN; }
     
+    /// Set PDN bit.
     Config & setPDN(bool newPDN) {
       if (newPDN) {
         readByte_ |= optionPDN;
@@ -91,12 +105,17 @@
       }
       return *this;
     }
+    
     /// @}
 
+    /// @name APU
+    /// @brief Active Pullup
     /// @{
-    /// Active Pullup
+    
+    /// Get APU bit.
     bool getAPU() const { return (readByte_ & optionAPU) == optionAPU; }
     
+    /// Set APU bit.
     Config & setAPU(bool newAPU) {
       if (newAPU) {
         readByte_ |= optionAPU;
@@ -105,6 +124,7 @@
       }
       return *this;
     }
+    
     /// @}
 
     /// Byte representation that is read from the device.
@@ -128,11 +148,10 @@
   /// Initialize hardware for use.
   MaximInterface_EXPORT error_code initialize(Config config = Config());
 
-  /// Write a new configuration to the device.
+  /// @brief Write a new configuration to the device.
   /// @param[in] config New configuration to write.
   MaximInterface_EXPORT error_code writeConfig(Config config);
 
-  /// @note Perform a 1-Wire triplet using the device command.
   MaximInterface_EXPORT virtual error_code triplet(TripletData & data);
 
   MaximInterface_EXPORT virtual error_code reset();
@@ -162,26 +181,27 @@
   /// @note Allow marking const since not public.
   error_code sendCommand(uint_least8_t cmd, uint_least8_t param) const;
 
-  /// Reads a register from the device.
+  /// @brief Reads a register from the device.
   /// @param reg Register to read from.
   /// @param[out] buf Buffer to hold read data.
   error_code readRegister(uint_least8_t reg, uint_least8_t & buf) const;
 
-  /// Reads the current register from the device.
+  /// @brief Reads the current register from the device.
   /// @param[out] buf Buffer to hold read data.
   error_code readRegister(uint_least8_t & buf) const;
 
 private:
-  /// Performs a soft reset on the device.
+  /// @brief Performs a soft reset on the device.
   /// @note This is not a 1-Wire Reset.
   error_code resetDevice();
 
+  /// @brief
   /// Polls the device status waiting for the 1-Wire Busy bit (1WB) to be cleared.
   /// @param[out] pStatus Optionally retrieve the status byte when 1WB cleared.
   /// @returns Success or TimeoutError if poll limit reached.
   error_code pollBusy(uint_least8_t * pStatus = NULL);
 
-  /// Ensure that the desired 1-Wire level is set in the configuration.
+  /// @brief Ensure that the desired 1-Wire level is set in the configuration.
   /// @param level Desired 1-Wire level.
   error_code configureLevel(Level level);
 
@@ -206,7 +226,7 @@
   DS2482_800(I2CMaster & i2c_bus, uint_least8_t adrs)
       : DS2482_DS2484(i2c_bus, adrs) {}
 
-  /// Select the active 1-Wire channel.
+  /// @brief Select the active 1-Wire channel.
   /// @param channel Channel number to select from 0 to 7.
   MaximInterface_EXPORT error_code selectChannel(int channel);
 };
@@ -214,7 +234,7 @@
 /// DS2484 I2C to 1-Wire Master
 class DS2484 : public DS2482_DS2484 {
 public:
-  /// 1-Wire port adjustment parameters.
+  /// @brief 1-Wire port adjustment parameters.
   /// @note See datasheet page 13.
   enum PortParameter {
     tRSTL = 0,
@@ -230,7 +250,7 @@
   explicit DS2484(I2CMaster & i2c_bus, uint_least8_t adrs = 0x30)
       : DS2482_DS2484(i2c_bus, adrs) {}
 
-  /// Adjust 1-Wire port parameters.
+  /// @brief Adjust 1-Wire port parameters.
   /// @param param Parameter to adjust.
   /// @param val New parameter value to set. Consult datasheet for value mappings.
   MaximInterface_EXPORT error_code adjustPort(PortParameter param, int val);
--- a/Devices/DS28C36_DS2476.cpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Devices/DS28C36_DS2476.cpp	Mon Mar 04 08:10:00 2019 -0600
@@ -670,9 +670,10 @@
 
 error_code readRomIdAndManId(DS28C36 & ds28c36, RomId::span romId,
                              ManId::span manId) {
-  DS28C36::RomOptions romOptions;
-  error_code result = ds28c36.readMemory(DS28C36::romOptionsPage, romOptions);
+  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);
   }
@@ -680,12 +681,26 @@
 }
 
 error_code enableCoprocessor(DS2476 & ds2476) {
-  DS2476::GpioControl gpioControl;
-  error_code result = ds2476.readMemory(DS2476::gpioControlPage, gpioControl);
+  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, gpioControl);
+      result = ds2476.writeMemory(DS2476::gpioControlPage, page);
+    }
+  }
+  return result;
+}
+
+error_code enableRomId(DS2476 & ds2476) {
+  DS2476::Page::array page;
+  error_code result = ds2476.readMemory(DS2476::romOptionsPage, page);
+  if (!result) {
+    DS2476::RomOptions romOptions(page);
+    if (!romOptions.romBlockDisable()) {
+      romOptions.setRomBlockDisable(true);
+      result = ds2476.writeMemory(DS2476::romOptionsPage, page);
     }
   }
   return result;
--- a/Devices/DS28C36_DS2476.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Devices/DS28C36_DS2476.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -61,7 +61,9 @@
     InvalidResponseError = 0x101 ///< Response does not match expected format.
   };
 
-  // Device memory pages.
+  /// @name Device memory pages
+  /// @{
+  
   static const int publicKeyAxPage = 16;
   static const int publicKeyAyPage = 17;
   static const int publicKeyBxPage = 18;
@@ -78,6 +80,8 @@
   static const int gpioControlPage = 29;
   static const int publicKeySxPage = 30;
   static const int publicKeySyPage = 31;
+  
+  /// @}
 
   /// Number of memory pages on the device.
   static const int memoryPages = 32;
@@ -101,24 +105,22 @@
   /// Holds a device memory page.
   typedef array_span<uint_least8_t, 32> Page;
 
-  /// Format page authentication input data.
+  // Format page authentication input data.
   class PageAuthenticationData;
 
-  /// Format authenticated write input data.
+  // Format authenticated write input data.
   class WriteAuthenticationData;
 
-  /// Format compute secret input data.
+  // Format compute secret input data.
   class ComputeSecretData;
 
-  /// Format encryption or decryption HMAC input data.
+  // Format encryption or decryption HMAC input data.
   class EncryptionHmacData;
 
-  /// Access fields in the ROM Options page. Can be used with writeMemory and
-  /// readMemory functions.
+  // Access fields in the ROM Options page.
   class RomOptions;
 
-  /// Access fields in the GPIO Control page. Can be used with writeMemory and
-  /// readMemory functions.
+  // Access fields in the GPIO Control page.
   class GpioControl;
 
   /// Page protection types.
@@ -148,33 +150,33 @@
 
   void setAddress(uint_least8_t address) { address_ = address & 0xFE; }
 
-  /// Write memory with no protection.
+  /// @brief Write memory with no protection.
   /// @param pageNum Number of page to write.
   /// @param page Data to write.
   MaximInterface_EXPORT error_code writeMemory(int pageNum,
                                                Page::const_span page);
 
-  /// Read memory with no protection.
+  /// @brief Read memory with no protection.
   /// @param pageNum Number of page to read.
   /// @param[out] page Data that was read.
   MaximInterface_EXPORT error_code readMemory(int pageNum, Page::span page);
 
-  /// Write the temporary buffer.
+  /// @brief Write the temporary buffer.
   /// @param data Data to write.
   MaximInterface_EXPORT error_code writeBuffer(span<const uint_least8_t> data);
 
-  /// Read the temporary buffer.
+  /// @brief Read the temporary buffer.
   /// @param[out] data Data that was read.
   MaximInterface_EXPORT error_code
   readBuffer(std::vector<uint_least8_t> & data);
 
-  /// Read the protection settings of a page.
+  /// @brief Read the protection settings of a page.
   /// @param pageNum Number of page to read.
   /// @param[out] protection Protection that was read.
   MaximInterface_EXPORT error_code
   readPageProtection(int pageNum, PageProtection & protection);
 
-  /// Set the protection settings of a page.
+  /// @brief Set the protection settings of a page.
   /// @param pageNum Number of page to write.
   /// @param protection Protection to write.
   MaximInterface_EXPORT error_code
@@ -183,11 +185,11 @@
   /// Decrement the decrement-only counter.
   MaximInterface_EXPORT error_code decrementCounter();
 
-  /// Read a block of random data from the RNG.
+  /// @brief Read a block of random data from the RNG.
   /// @param[out] data Random data from RNG with length from 1 to 64.
   MaximInterface_EXPORT error_code readRng(span<uint_least8_t> data);
 
-  /// Read memory with encryption.
+  /// @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.
@@ -196,29 +198,30 @@
   encryptedReadMemory(int pageNum, SecretNum secretNum,
                       EncryptionChallenge::span challenge, Page::span data);
 
-  /// Compute and read page authentication with ECDSA.
+  /// @brief Compute and read page authentication with ECDSA.
   /// @param pageNum Number of page to authenticate.
-  /// @param keyNum Private key to use for authentication.
+  /// @param keyNum
+  /// Private key to use for authentication.
   /// Key S cannot be used with this command.
   /// @param[out] signature Computed page signature.
   MaximInterface_EXPORT error_code computeAndReadPageAuthentication(
       int pageNum, KeyNum keyNum, Ecc256::Signature::span signature);
 
-  /// Compute and read page authentication with HMAC.
+  /// @brief Compute and read page authentication with HMAC.
   /// @param pageNum Number of page to authenticate.
   /// @param secretNum Secret to use for authentication.
   /// @param[out] hmac Computed page HMAC.
   MaximInterface_EXPORT error_code computeAndReadPageAuthentication(
       int pageNum, SecretNum secretNum, Sha256::Hash::span hmac);
 
-  /// Write with SHA2 authentication.
+  /// @brief Write with SHA2 authentication.
   /// @param pageNum Number of page to write.
   /// @param secretNum Secret to use for authentication.
   /// @param page Data to write.
   MaximInterface_EXPORT error_code authenticatedSha2WriteMemory(
       int pageNum, SecretNum secretNum, Page::const_span page);
 
-  /// Compute SHA2 secret and optionally lock.
+  /// @brief Compute SHA2 secret and optionally lock.
   /// @param pageNum Number of page to use in computation.
   /// @param msecretNum Master secret to use in computation.
   /// @param dsecretNum Destination secret to receive the computation result.
@@ -228,13 +231,13 @@
   computeAndLockSha2Secret(int pageNum, SecretNum msecretNum,
                            SecretNum dsecretNum, bool writeProtectEnable);
 
-  /// Generate a new ECDSA key pair.
+  /// @brief Generate a new ECDSA key pair.
   /// @param keyNum Key to generate. Key S cannot be used with this command.
   /// @param writeProtectEnable True to lock the key against further writes.
   MaximInterface_EXPORT error_code
   generateEcc256KeyPair(KeyNum keyNum, bool writeProtectEnable);
 
-  /// Compute a hash over multiple blocks.
+  /// @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
@@ -242,7 +245,7 @@
   MaximInterface_EXPORT error_code computeMultiblockHash(
       bool firstBlock, bool lastBlock, span<const uint_least8_t> data);
 
-  /// Verify ECDSA signature.
+  /// @brief Verify ECDSA signature.
   /// @param keyNum Public key to use for verification.
   /// @param hashType Source of the data hash input.
   /// @param signature Signature to verify.
@@ -252,18 +255,20 @@
       KeyNum keyNum, HashType hashType, Ecc256::Signature::const_span signature,
       PioState pioa = Unchanged, PioState piob = Unchanged);
 
-  /// Authenticate a public key for authenticated writes or encrypted reads with ECDH.
+  /// @brief
+  /// Authenticate a public key for authenticated writes or encrypted reads
+  /// with ECDH.
   /// @param authWrites True to select authentication for writes.
   /// @param ecdh True to select ECDH key exchange.
-  /// @param keyNum Private key to use for ECDH key exchange.
-  /// Key A or B can be selected.
+  /// @param keyNum
+  /// Private key to use for ECDH key exchange. Key A or B can be selected.
   /// @param csOffset Certificate customization field ending offset in buffer.
   /// @param signature Signature to use for authentication of public key S.
   MaximInterface_EXPORT error_code authenticateEcdsaPublicKey(
       bool authWrites, bool ecdh, KeyNum keyNum, int csOffset,
       Ecc256::Signature::const_span signature);
 
-  /// Write with ECDSA authentication.
+  /// @brief Write with ECDSA authentication.
   /// @param pageNum Number of page to write.
   /// @param page Data to write.
   MaximInterface_EXPORT error_code
@@ -316,19 +321,20 @@
   DS2476(Sleep & sleep, I2CMaster & master, uint_least8_t address = 0x76)
       : DS28C36(sleep, master, address) {}
 
-  /// Generate ECDSA signature.
-  /// @param keyNum Private key to use to create signature.
+  /// @brief Generate ECDSA signature.
+  /// @param keyNum
+  /// Private key to use to create signature.
   /// Key S cannot be used with this command.
   /// @param[out] signature Computed signature.
   MaximInterface_EXPORT error_code
   generateEcdsaSignature(KeyNum keyNum, Ecc256::Signature::span signature);
 
-  /// Compute unique SHA2 secret.
+  /// @brief Compute unique SHA2 secret.
   /// @param msecretNum Master secret to use in computation.
   MaximInterface_EXPORT error_code
   computeSha2UniqueSecret(SecretNum msecretNum);
 
-  /// Compute SHA2 HMAC.
+  /// @brief Compute SHA2 HMAC.
   /// @param[out] hmac Computed HMAC.
   MaximInterface_EXPORT error_code computeSha2Hmac(Sha256::Hash::span hmac);
 };
@@ -337,12 +343,15 @@
   return error_code(e, DS28C36::errorCategory());
 }
 
+/// @brief
 /// Hash arbitrary length data with successive Compute Multiblock Hash commands.
+/// @param ds28c36 Device for computation.
 /// @param data Data to hash.
 MaximInterface_EXPORT error_code
 computeMultiblockHash(DS28C36 & ds28c36, span<const uint_least8_t> data);
 
-/// Verify ECDSA signature.
+/// @brief Verify ECDSA signature.
+/// @param ds28c36 Device for computation.
 /// @param publicKey Public key to use for verification.
 /// @param data Data to verify.
 /// @param signature Signature to verify.
@@ -354,7 +363,8 @@
     DS28C36::PioState pioa = DS28C36::Unchanged,
     DS28C36::PioState piob = DS28C36::Unchanged);
 
-/// Verify ECDSA signature.
+/// @brief Verify ECDSA signature.
+/// @param ds28c36 Device for computation.
 /// @param publicKey
 /// Public key to use for verification which is loaded into Public Key S.
 /// @param data Data to verify.
@@ -367,18 +377,27 @@
     DS28C36::PioState pioa = DS28C36::Unchanged,
     DS28C36::PioState piob = DS28C36::Unchanged);
 
+/// @brief
 /// Read the device ROM ID and MAN ID using the Read Memory command on the
 /// ROM Options page.
+/// @param ds28c36 Device to read.
 /// @param[out] romId Read ROM ID valid when operation is successful.
 /// @param[out] manId Read MAN ID valid when operation is successful.
 MaximInterface_EXPORT error_code readRomIdAndManId(DS28C36 & ds28c36,
                                                    RomId::span romId,
                                                    ManId::span manId);
 
+/// @brief
 /// Enable coprocessor functionality on the DS2476 by writing to the
-/// ROM Options page.
+/// GPIO Control page.
 MaximInterface_EXPORT error_code enableCoprocessor(DS2476 & ds2476);
 
+/// @brief
+/// Disable blocking of the ROM ID on the DS2476 by writing to the
+/// ROM Options page.
+MaximInterface_EXPORT error_code enableRomId(DS2476 & ds2476);
+
+/// Format page authentication input data.
 class DS28C36::PageAuthenticationData {
 public:
   typedef array_span<uint_least8_t,
@@ -390,80 +409,110 @@
   /// Formatted data result.
   Result::const_span result() const { return result_; }
 
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
   /// @{
-  /// 1-Wire ROM ID of the device.
+  
+  /// Get mutable ROM ID.
   RomId::span romId() {
     return make_span(result_).subspan<romIdIdx, RomId::size>();
   }
 
+  /// Get immutable ROM ID.
   RomId::const_span romId() const {
     return const_cast<PageAuthenticationData &>(*this).romId();
   }
 
+  /// Set ROM ID.
   PageAuthenticationData & setRomId(RomId::const_span romId) {
     copy(romId, this->romId());
     return *this;
   }
 
+  /// Set ROM ID for use in anonymous mode.
   MaximInterface_EXPORT PageAuthenticationData & setAnonymousRomId();
+  
   /// @}
 
+  /// @name Page
+  /// @brief Data from a device memory page.
   /// @{
-  /// Data from a device memory page.
+
+  /// Get mutable page.
   Page::span page() {
     return make_span(result_).subspan<pageIdx, Page::size>();
   }
 
+  /// Get immutable page.
   Page::const_span page() const {
     return const_cast<PageAuthenticationData &>(*this).page();
   }
 
+  /// Set page.
   PageAuthenticationData & setPage(Page::const_span page) {
     copy(page, this->page());
     return *this;
   }
+  
   /// @}
 
+  /// @name Challenge
+  /// @brief Random challenge used to prevent replay attacks.
   /// @{
-  /// Random challenge used to prevent replay attacks.
+  
+  /// Get mutable Challenge.
   Page::span challenge() {
     return make_span(result_).subspan<challengeIdx, Page::size>();
   }
 
+  /// Get immutable Challenge.
   Page::const_span challenge() const {
     return const_cast<PageAuthenticationData &>(*this).challenge();
   }
 
+  /// Set Challenge.
   PageAuthenticationData & setChallenge(Page::const_span challenge) {
     copy(challenge, this->challenge());
     return *this;
   }
+  
   /// @}
 
+  /// @name Page number
+  /// @brief Number of the page to use data from.
   /// @{
-  /// Number of the page to use data from.
+  
+  /// Get page number.
   int pageNum() const { return result_[pageNumIdx]; }
 
+  /// Set page number.
   PageAuthenticationData & setPageNum(int pageNum) {
     result_[pageNumIdx] = pageNum;
     return *this;
   }
+  
   /// @}
 
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
   /// @{
-  /// Manufacturer ID of the device.
+  
+  /// Get mutable MAN ID.
   ManId::span manId() {
     return make_span(result_).subspan<manIdIdx, ManId::size>();
   }
 
+  /// Get immutable MAN ID.
   ManId::const_span manId() const {
     return const_cast<PageAuthenticationData &>(*this).manId();
   }
 
+  /// Set MAN ID.
   PageAuthenticationData & setManId(ManId::const_span manId) {
     copy(manId, this->manId());
     return *this;
   }
+  
   /// @}
 
 private:
@@ -478,6 +527,7 @@
   Result::array result_;
 };
 
+/// Format authenticated write input data.
 class DS28C36::WriteAuthenticationData {
 public:
   typedef PageAuthenticationData::Result Result;
@@ -487,73 +537,104 @@
   /// Formatted data result.
   Result::const_span result() const { return data.result(); }
 
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
   /// @{
-  /// 1-Wire ROM ID of the device.
+  
+  /// Get mutable ROM ID.
   RomId::span romId() { return data.romId(); }
 
+  /// Get immutable ROM ID.
   RomId::const_span romId() const { return data.romId(); }
 
+  /// Set ROM ID.
   WriteAuthenticationData & setRomId(RomId::const_span romId) {
     data.setRomId(romId);
     return *this;
   }
 
+  /// Set ROM ID for use in anonymous mode.
   WriteAuthenticationData & setAnonymousRomId() {
     data.setAnonymousRomId();
     return *this;
   }
+  
   /// @}
 
+  /// @name Old page
+  /// @brief Existing data contained in the page.
   /// @{
-  /// Existing data contained in the page.
+  
+  /// Get mutable old page.
   Page::span oldPage() { return data.page(); }
 
+  /// Get immutable old page.
   Page::const_span oldPage() const { return data.page(); }
 
+  /// Set old page.
   WriteAuthenticationData & setOldPage(Page::const_span oldPage) {
     data.setPage(oldPage);
     return *this;
   }
+  
   /// @}
 
+  /// @name New page
+  /// @brief New data to write to the page.
   /// @{
-  /// New data to write to the page.
+  
+  /// Get mutable new page.
   Page::span newPage() { return data.challenge(); }
 
+  /// Get immutable new page.
   Page::const_span newPage() const { return data.challenge(); }
 
+  /// Set new page.
   WriteAuthenticationData & setNewPage(Page::const_span newPage) {
     data.setChallenge(newPage);
     return *this;
   }
+  
   /// @}
 
+  /// @name Page number
+  /// @brief Page number for write operation.
   /// @{
-  /// Page number for write operation.
+
+  /// Get page number.
   int pageNum() const { return data.pageNum(); }
 
+  /// Set page number.
   WriteAuthenticationData & setPageNum(int pageNum) {
     data.setPageNum(pageNum);
     return *this;
   }
+  
   /// @}
 
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
   /// @{
-  /// Manufacturer ID of the device.
+
+  /// Get mutable MAN ID.
   ManId::span manId() { return data.manId(); }
 
+  /// Get immutable MAN ID.
   ManId::const_span manId() const { return data.manId(); }
 
+  /// Set MAN ID.
   WriteAuthenticationData & setManId(ManId::const_span manId) {
     data.setManId(manId);
     return *this;
   }
+  
   /// @}
 
 private:
   PageAuthenticationData data;
 };
 
+/// Format compute secret input data.
 class DS28C36::ComputeSecretData {
 public:
   typedef PageAuthenticationData::Result Result;
@@ -563,68 +644,98 @@
   /// Formatted data result.
   Result::const_span result() const { return data.result(); }
 
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
   /// @{
-  /// 1-Wire ROM ID of the device.
+  
+  /// Get mutable ROM ID.
   RomId::span romId() { return data.romId(); }
 
+  /// Get immutable ROM ID.
   RomId::const_span romId() const { return data.romId(); }
 
+  /// Set ROM ID.
   ComputeSecretData & setRomId(RomId::const_span romId) {
     data.setRomId(romId);
     return *this;
   }
+  
   /// @}
 
+  /// @name Binding Data
+  /// @brief Binding Data contained in the selected page.
   /// @{
-  /// Binding Data contained in the selected page.
+  
+  /// Get mutable Binding Data.
   Page::span bindingData() { return data.page(); }
 
+  /// Get immutable Binding Data.
   Page::const_span bindingData() const { return data.page(); }
 
+  /// Set Binding Data.
   ComputeSecretData & setBindingData(Page::const_span bindingData) {
     data.setPage(bindingData);
     return *this;
   }
+  
   /// @}
 
+  /// @name Partial Secret
+  /// @brief Partial Secret used for customization.
   /// @{
-  /// Partial Secret used for customization.
+  
+  /// Get mutable Partial Secret.
   Page::span partialSecret() { return data.challenge(); }
 
+  /// Get immutable Partial Secret.
   Page::const_span partialSecret() const { return data.challenge(); }
 
+  /// Set Partial Secret.
   ComputeSecretData & setPartialSecret(Page::const_span partialSecret) {
     data.setChallenge(partialSecret);
     return *this;
   }
+  
   /// @}
 
+  /// @name Page number
+  /// @brief Page number for Binding Data.
   /// @{
-  /// Page number for Binding Data.
+  
+  /// Get page number.
   int pageNum() const { return data.pageNum(); }
 
+  /// Set page number.
   ComputeSecretData & setPageNum(int pageNum) {
     data.setPageNum(pageNum);
     return *this;
   }
+  
   /// @}
 
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
   /// @{
-  /// Manufacturer ID of the device.
+  
+  /// Get mutable MAN ID.
   ManId::span manId() { return data.manId(); }
 
+  /// Get immutable MAN ID.
   ManId::const_span manId() const { return data.manId(); }
 
+  /// Set MAN ID.
   ComputeSecretData & setManId(ManId::const_span manId) {
     data.setManId(manId);
     return *this;
   }
+  
   /// @}
 
 private:
   PageAuthenticationData data;
 };
 
+/// Format encryption or decryption HMAC input data.
 class DS28C36::EncryptionHmacData {
 public:
   typedef array_span<uint_least8_t,
@@ -636,66 +747,90 @@
   /// Formatted data result.
   Result::const_span result() const { return result_; }
 
+  /// @name Encryption Challenge
+  /// @brief Random challenge used to prevent replay attacks.
   /// @{
-  /// Random challenge used to prevent replay attacks.
+  
+  /// Get mutable Encryption Challenge.
   EncryptionChallenge::span encryptionChallenge() {
     return make_span(result_)
         .subspan<encryptionChallengeIdx, EncryptionChallenge::size>();
   }
 
+  /// Get immutable Encryption Challenge.
   EncryptionChallenge::const_span encryptionChallenge() const {
     return const_cast<EncryptionHmacData &>(*this).encryptionChallenge();
   }
 
+  /// Set Encryption Challenge.
   EncryptionHmacData &
   setEncryptionChallenge(EncryptionChallenge::const_span encryptionChallenge) {
     copy(encryptionChallenge, this->encryptionChallenge());
     return *this;
   }
+  
   /// @}
 
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
   /// @{
-  /// 1-Wire ROM ID of the device.
+  
+  /// Get mutable ROM ID.
   RomId::span romId() {
     return make_span(result_).subspan<romIdIdx, RomId::size>();
   }
 
+  /// Get immutable ROM ID.
   RomId::const_span romId() const {
     return const_cast<EncryptionHmacData &>(*this).romId();
   }
 
+  /// Set ROM ID.
   EncryptionHmacData & setRomId(RomId::const_span romId) {
     copy(romId, this->romId());
     return *this;
   }
 
+  /// Set ROM ID for use in anonymous mode.
   MaximInterface_EXPORT EncryptionHmacData & setAnonymousRomId();
+  
   /// @}
 
+  /// @name Page number
+  /// @brief Number of the page to use data from.
   /// @{
-  /// Number of the page to use data from.
+  
+  /// Get page number.
   int pageNum() const { return result_[pageNumIdx]; }
 
+  /// Set page number.
   EncryptionHmacData & setPageNum(int pageNum) {
     result_[pageNumIdx] = pageNum;
     return *this;
   }
+  
   /// @}
 
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
   /// @{
-  /// Manufacturer ID of the device.
+
+  /// Get mutable MAN ID.
   ManId::span manId() {
     return make_span(result_).subspan<manIdIdx, ManId::size>();
   }
 
+  /// Get immutable MAN ID.
   ManId::const_span manId() const {
     return const_cast<EncryptionHmacData &>(*this).manId();
   }
 
+  /// Set MAN ID.
   EncryptionHmacData & setManId(ManId::const_span manId) {
     copy(manId, this->manId());
     return *this;
   }
+  
   /// @}
 
 private:
@@ -710,51 +845,64 @@
   Result::array result_;
 };
 
+/// Access fields in the ROM Options page.
 class DS28C36::RomOptions {
 public:
-  operator Page::const_span() const { return page; }
-  operator Page::span() { return page; }
+  explicit RomOptions(Page::span page) : page(page) {}
 
-  bool anonymous() const { return page[anonymousIdx] == anonymousValue; }
+  bool romBlockDisable() const {
+    return page[romBlockDisableIdx] == enabledValue;
+  }
+  
+  RomOptions & setRomBlockDisable(bool romBlockDisable) {
+    page[romBlockDisableIdx] = (romBlockDisable ? enabledValue : 0);
+    return *this;
+  }
+  
+  bool anonymous() const { return page[anonymousIdx] == enabledValue; }
 
-  void setAnonymous(bool anonymous) {
-    page[anonymousIdx] = (anonymous ? anonymousValue : 0);
+  RomOptions & setAnonymous(bool anonymous) {
+    page[anonymousIdx] = (anonymous ? enabledValue : 0);
+    return *this;
   }
 
   ManId::const_span manId() const {
-    return make_span(page).subspan<22, ManId::size>();
+    return page.subspan<22, ManId::size>();
   }
 
   RomId::const_span romId() const {
-    return make_span(page).subspan<24, RomId::size>();
+    return page.subspan<24, RomId::size>();
   }
 
 private:
-  static const Page::array::size_type anonymousIdx = 1;
-  static const Page::array::value_type anonymousValue = 0xAA;
+  static const Page::span::index_type romBlockDisableIdx = 0;
+  static const Page::span::index_type anonymousIdx = 1;
+  static const Page::span::value_type enabledValue = 0xAA;
 
-  Page::array page;
+  Page::span page;
 };
 
+/// Access fields in the GPIO Control page.
 class DS28C36::GpioControl {
 public:
-  operator Page::const_span() const { return page; }
-  operator Page::span() { return page; }
+  explicit GpioControl(Page::span page) : page(page) {}
 
   bool pioaConducting() const {
     return page[pioaConductingIdx] == pioConductingValue;
   }
 
-  void setPioaConducting(bool pioaConducting) {
+  GpioControl & setPioaConducting(bool pioaConducting) {
     page[pioaConductingIdx] = (pioaConducting ? pioConductingValue : 0x55);
+    return *this;
   }
 
   bool piobConducting() const {
     return page[piobConductingIdx] == pioConductingValue;
   }
 
-  void setPiobConducting(bool piobConducting) {
+  GpioControl & setPiobConducting(bool piobConducting) {
     page[piobConductingIdx] = (piobConducting ? pioConductingValue : 0x55);
+    return *this;
   }
 
   bool pioaLevel() const { return page[2] == pioLevelValue; }
@@ -762,12 +910,12 @@
   bool piobLevel() const { return page[3] == pioLevelValue; }
 
 private:
-  static const Page::array::size_type pioaConductingIdx = 0;
-  static const Page::array::size_type piobConductingIdx = 1;
-  static const Page::array::value_type pioConductingValue = 0xAA;
-  static const Page::array::value_type pioLevelValue = 0x55;
+  static const Page::span::index_type pioaConductingIdx = 0;
+  static const Page::span::index_type piobConductingIdx = 1;
+  static const Page::span::value_type pioConductingValue = 0xAA;
+  static const Page::span::value_type pioLevelValue = 0x55;
 
-  Page::array page;
+  Page::span page;
 };
 
 } // namespace MaximInterface
--- a/Devices/DS28E15_22_25.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Devices/DS28E15_22_25.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -44,6 +44,7 @@
 
 namespace MaximInterface {
 
+/// @brief
 /// Interface to the DS28E15/22/25 series of authenticators
 /// including low power variants.
 class DS28E15_22_25 {
@@ -71,17 +72,17 @@
     bool secretLocked() const { return PB2 & 0x01; }
   };
 
-  /// Represents the status of a memory protection block.
+  // Represents the status of a memory protection block.
   class BlockProtection;
 
-  /// Format data to hash for an Authenticated Write to a memory segment.
+  // Format data to hash for an Authenticated Write to a memory segment.
   class SegmentWriteMacData;
 
-  /// Format data to hash for an Authenticated Write to a memory protection block.
+  // Format data to hash for an Authenticated Write to a memory protection block.
   class ProtectionWriteMacData;
 
-  /// Format data to hash for device authentication or computing the next secret
-  /// from the existing secret.
+  // Format data to hash for device authentication or computing the next secret
+  // from the existing secret.
   class AuthenticationData;
 
   void setSleep(Sleep & sleep) { this->sleep = &sleep; }
@@ -95,20 +96,20 @@
   // Const member functions should not affect the state of the memory,
   // block protection, or secret on the device.
 
-  /// Read memory segment using the Read Memory command on the device.
+  /// @brief Read memory segment using the Read Memory command on the device.
   /// @param pageNum Page number for read operation.
   /// @param segmentNum Segment number within page for read operation.
   /// @param[out] data Buffer to read data from the segment into.
   MaximInterface_EXPORT error_code readSegment(int pageNum, int segmentNum,
                                                Segment::span data) const;
 
-  /// Continue an in-progress readSegment operation.
+  /// @brief Continue an in-progress readSegment operation.
   /// @note A CRC16 will encountered after reading the last segment of a page.
   /// @param[out] data Buffer to read data from the segment into.
   MaximInterface_EXPORT error_code
   continueReadSegment(Segment::span data) const;
 
-  /// Write memory segment using the Write Memory command.
+  /// @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.
@@ -116,21 +117,22 @@
   MaximInterface_EXPORT error_code writeSegment(int pageNum, int segmentNum,
                                                 Segment::const_span data);
 
-  /// Continue an in-progress Write Memory command.
+  /// @brief Continue an in-progress Write Memory command.
   /// @param[in] data Data to write to the memory segment.
   MaximInterface_EXPORT error_code
   continueWriteSegment(Segment::const_span data);
 
-  /// Read memory page using the Read Memory command on the device.
+  /// @brief Read memory page using the Read Memory command on the device.
   /// @param pageNum Page number for write operation.
   /// @param[out] rdbuf Buffer to read data from the page into.
   MaximInterface_EXPORT error_code readPage(int pageNum,
                                             Page::span rdbuf) const;
 
-  /// Continue an in-progress readPageOperation.
+  /// @brief Continue an in-progress readPageOperation.
   /// @param[out] rdbuf Buffer to read data from the page into.
   MaximInterface_EXPORT error_code continueReadPage(Page::span rdbuf) const;
 
+  /// @brief
   /// Perform a Compute Page MAC command on the device.
   /// Read back the MAC and verify the CRC16.
   /// @param pageNum Page number to use for the computation.
@@ -139,13 +141,16 @@
   MaximInterface_EXPORT error_code
   computeReadPageMac(int pageNum, bool anon, Sha256::Hash::span mac) const;
 
+  /// @brief
   /// Update the status of a memory protection block using the
   /// Write Page Protection command.
-  /// @param protection Desired protection status for the block.
-  ///                   It is not possible to disable existing protections.
+  /// @param protection
+  /// Desired protection status for the block.
+  /// It is not possible to disable existing protections.
   MaximInterface_EXPORT error_code
   writeBlockProtection(BlockProtection protection);
 
+  /// @brief
   /// Update the status of a memory protection block using the
   /// Authenticated Write Page Protection command.
   /// @param newProtection New protection status to write.
@@ -153,17 +158,19 @@
   MaximInterface_EXPORT error_code writeAuthBlockProtection(
       BlockProtection newProtection, Sha256::Hash::const_span mac);
 
-  /// Perform Load and Lock Secret command on the device.
+  /// @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.
+  /// @param lock
+  /// Prevent further changes to the secret on the device after loading.
   MaximInterface_EXPORT error_code loadSecret(bool lock);
 
-  /// Perform a Compute and Lock Secret command on the device.
+  /// @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.
+  /// @param lock
+  /// Prevent further changes to the secret on the device after computing.
   MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock);
 
-  /// Read the personality bytes using the Read Status command.
+  /// @brief Read the personality bytes using the Read Status command.
   /// @param[out] personality Receives personality read from device.
   MaximInterface_EXPORT error_code
   readPersonality(Personality & personality) const;
@@ -242,21 +249,22 @@
   DS28EL15(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
       : DS28E15_22_25(sleep, master, selectRom) {}
 
-  /// Perform Write Scratchpad operation on the device.
+  /// @brief Perform Write Scratchpad operation on the device.
   /// @param[in] data Data to write to the scratchpad.
   MaximInterface_EXPORT error_code writeScratchpad(Scratchpad::const_span data);
 
-  /// Perform a Read Scratchpad operation on the device.
+  /// @brief Perform a Read Scratchpad operation on the device.
   /// @param[out] data Buffer to read data from the scratchpad into.
   MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span data) const;
 
+  /// @brief
   /// Read the status of a memory protection block using the Read Status command.
   /// @param blockNum Block number to to read status of.
   /// @param[out] protection Receives protection status read from device.
   MaximInterface_EXPORT error_code
   readBlockProtection(int blockNum, BlockProtection & protection) const;
 
-  /// Write memory segment using the Authenticated Write Memory command.
+  /// @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.
@@ -265,12 +273,13 @@
   writeAuthSegment(int pageNum, int segmentNum, Segment::const_span newData,
                    Sha256::Hash::const_span mac);
 
-  /// Continue an in-progress Authenticated Write Memory command.
+  /// @brief Continue an in-progress Authenticated Write Memory command.
   /// @param[in] newData New data to write to the segment.
   /// @param[in] mac Write MAC computed for this operation.
   MaximInterface_EXPORT error_code continueWriteAuthSegment(
       Segment::const_span newData, Sha256::Hash::const_span mac);
 
+  /// @brief
   /// Read the status of all memory protection blocks using the Read Status command.
   /// @param[out] protection Receives protection statuses read from device.
   MaximInterface_EXPORT error_code readAllBlockProtection(
@@ -283,14 +292,16 @@
   DS28E15(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
       : DS28EL15(sleep, master, selectRom) {}
 
-  /// Perform Load and Lock Secret command on the device.
+  /// @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.
+  /// @param lock
+  /// Prevent further changes to the secret on the device after loading.
   MaximInterface_EXPORT error_code loadSecret(bool lock);
 
-  /// Perform a Compute and Lock Secret command on the device.
+  /// @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.
+  /// @param lock
+  /// Prevent further changes to the secret on the device after computing.
   MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock);
 };
 
@@ -304,14 +315,81 @@
   DS28EL22(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
       : DS28E15_22_25(sleep, master, selectRom) {}
 
-  /// Perform Write Scratchpad operation on the device.
+  /// @brief Perform Write Scratchpad operation on the device.
   /// @param[in] data Data to write to the scratchpad.
   MaximInterface_EXPORT error_code writeScratchpad(Scratchpad::const_span data);
 
-  /// Perform a Read Scratchpad operation on the device.
+  /// @brief Perform a Read Scratchpad operation on the device.
   /// @param[out] data Buffer to read data from the scratchpad into.
   MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span data) const;
 
+  /// @brief
+  /// Read the status of a memory protection block using the Read Status command.
+  /// @param blockNum Block number to to read status of.
+  /// @param[out] protection Receives protection status read from device.
+  MaximInterface_EXPORT error_code
+  readBlockProtection(int blockNum, BlockProtection & protection) const;
+
+  /// @brief Write memory segment using the Authenticated Write Memory command.
+  /// @param pageNum Page number for write operation.
+  /// @param segmentNum Segment number within page for write operation.
+  /// @param[in] newData New data to write to the segment.
+  /// @param[in] mac Write MAC computed for this operation.
+  MaximInterface_EXPORT error_code
+  writeAuthSegment(int pageNum, int segmentNum, Segment::const_span newData,
+                   Sha256::Hash::const_span mac);
+
+  /// @brief Continue an in-progress Authenticated Write Memory command.
+  /// @param[in] newData New data to write to the segment.
+  /// @param[in] mac Write MAC computed for this operation.
+  MaximInterface_EXPORT error_code continueWriteAuthSegment(
+      Segment::const_span newData, Sha256::Hash::const_span mac);
+
+  /// @brief
+  /// Read the status of all memory protection blocks using the Read Status command.
+  /// @param[out] protection Receives protection statuses read from device.
+  MaximInterface_EXPORT error_code readAllBlockProtection(
+      span<BlockProtection, protectionBlocks> protection) const;
+};
+
+/// Interface to the DS28E22 authenticator.
+class DS28E22 : public DS28EL22 {
+public:
+  DS28E22(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
+      : DS28EL22(sleep, master, selectRom) {}
+
+  /// @brief Perform Load and Lock Secret command on the device.
+  /// @note The secret should already be stored in the scratchpad on the device.
+  /// @param lock
+  /// Prevent further changes to the secret on the device after loading.
+  MaximInterface_EXPORT error_code loadSecret(bool lock);
+
+  /// @brief Perform a Compute and Lock Secret command on the device.
+  /// @param pageNum Page number to use as the binding data.
+  /// @param lock
+  /// Prevent further changes to the secret on the device after computing.
+  MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock);
+};
+
+/// Interface to the DS28EL25 (low power) authenticator.
+class DS28EL25 : public DS28E15_22_25 {
+public:
+  // DS28E15_22_25 traits
+  static const int memoryPages = 16;
+  static const int protectionBlocks = 8;
+
+  DS28EL25(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
+      : DS28E15_22_25(sleep, master, selectRom) {}
+
+  /// @brief Perform Write Scratchpad operation on the device.
+  /// @param[in] data Data to write to the scratchpad.
+  MaximInterface_EXPORT error_code writeScratchpad(Scratchpad::const_span data);
+
+  /// @brief Perform a Read Scratchpad operation on the device.
+  /// @param[out] data Buffer to read data from the scratchpad into.
+  MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span data) const;
+
+  /// @brief
   /// Read the status of a memory protection block using the Read Status command.
   /// @param blockNum Block number to to read status of.
   /// @param[out] protection Receives protection status read from device.
@@ -327,74 +405,13 @@
   writeAuthSegment(int pageNum, int segmentNum, Segment::const_span newData,
                    Sha256::Hash::const_span mac);
 
-  /// Continue an in-progress Authenticated Write Memory command.
+  /// @brief Continue an in-progress Authenticated Write Memory command.
   /// @param[in] newData New data to write to the segment.
   /// @param[in] mac Write MAC computed for this operation.
   MaximInterface_EXPORT error_code continueWriteAuthSegment(
       Segment::const_span newData, Sha256::Hash::const_span mac);
 
-  /// Read the status of all memory protection blocks using the Read Status command.
-  /// @param[out] protection Receives protection statuses read from device.
-  MaximInterface_EXPORT error_code readAllBlockProtection(
-      span<BlockProtection, protectionBlocks> protection) const;
-};
-
-/// Interface to the DS28E22 authenticator.
-class DS28E22 : public DS28EL22 {
-public:
-  DS28E22(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
-      : DS28EL22(sleep, master, selectRom) {}
-
-  /// Perform Load and Lock Secret command on the device.
-  /// @note The secret should already be stored in the scratchpad on the device.
-  /// @param lock Prevent further changes to the secret on the device after loading.
-  MaximInterface_EXPORT error_code loadSecret(bool lock);
-
-  /// Perform a Compute and Lock Secret command on the device.
-  /// @param pageNum Page number to use as the binding data.
-  /// @param lock Prevent further changes to the secret on the device after computing.
-  MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock);
-};
-
-/// Interface to the DS28EL25 (low power) authenticator.
-class DS28EL25 : public DS28E15_22_25 {
-public:
-  // DS28E15_22_25 traits
-  static const int memoryPages = 16;
-  static const int protectionBlocks = 8;
-
-  DS28EL25(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
-      : DS28E15_22_25(sleep, master, selectRom) {}
-
-  /// Perform Write Scratchpad operation on the device.
-  /// @param[in] data Data to write to the scratchpad.
-  MaximInterface_EXPORT error_code writeScratchpad(Scratchpad::const_span data);
-
-  /// Perform a Read Scratchpad operation on the device.
-  /// @param[out] data Buffer to read data from the scratchpad into.
-  MaximInterface_EXPORT error_code readScratchpad(Scratchpad::span data) const;
-
-  /// Read the status of a memory protection block using the Read Status command.
-  /// @param blockNum Block number to to read status of.
-  /// @param[out] protection Receives protection status read from device.
-  MaximInterface_EXPORT error_code
-  readBlockProtection(int blockNum, BlockProtection & protection) const;
-
-  /// Write memory segment using the Authenticated Write Memory command.
-  /// @param pageNum Page number for write operation.
-  /// @param segmentNum Segment number within page for write operation.
-  /// @param[in] newData New data to write to the segment.
-  /// @param[in] mac Write MAC computed for this operation.
-  MaximInterface_EXPORT error_code
-  writeAuthSegment(int pageNum, int segmentNum, Segment::const_span newData,
-                   Sha256::Hash::const_span mac);
-
-  /// Continue an in-progress Authenticated Write Memory command.
-  /// @param[in] newData New data to write to the segment.
-  /// @param[in] mac Write MAC computed for this operation.
-  MaximInterface_EXPORT error_code continueWriteAuthSegment(
-      Segment::const_span newData, Sha256::Hash::const_span mac);
-
+  /// @brief
   /// Read the status of all memory protection blocks using the Read Status command.
   /// @param[out] protection Receives protection statuses read from device.
   MaximInterface_EXPORT error_code readAllBlockProtection(
@@ -407,17 +424,19 @@
   DS28E25(Sleep & sleep, OneWireMaster & master, const SelectRom & selectRom)
       : DS28EL25(sleep, master, selectRom) {}
 
-  /// Perform Load and Lock Secret command on the device.
+  /// @brief Perform Load and Lock Secret command on the device.
   /// @note The secret should already be stored in the scratchpad on the device.
   /// @param lock Prevent further changes to the secret on the device after loading.
   MaximInterface_EXPORT error_code loadSecret(bool lock);
 
-  /// Perform a Compute and Lock Secret command on the device.
+  /// @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.
+  /// @param lock
+  /// Prevent further changes to the secret on the device after computing.
   MaximInterface_EXPORT error_code computeSecret(int pageNum, bool lock);
 };
 
+/// Represents the status of a memory protection block.
 class DS28E15_22_25::BlockProtection {
 public:
   explicit BlockProtection(uint_least8_t status = 0x00) : status(status) {}
@@ -437,7 +456,7 @@
   /// Set the Block Number which is indexed from zero.
   MaximInterface_EXPORT BlockProtection & setBlockNum(int blockNum);
 
-  /// Get the Read Protection status.
+  /// @brief Get the Read Protection status.
   /// @returns True if Read Protection is enabled.
   bool readProtection() const {
     return ((status & readProtectionMask) == readProtectionMask);
@@ -447,7 +466,7 @@
   MaximInterface_EXPORT BlockProtection &
   setReadProtection(bool readProtection);
 
-  /// Get the Write Protection status.
+  /// @brief Get the Write Protection status.
   /// @returns True if Write Protection is enabled.
   bool writeProtection() const {
     return ((status & writeProtectionMask) == writeProtectionMask);
@@ -457,7 +476,7 @@
   MaximInterface_EXPORT BlockProtection &
   setWriteProtection(bool writeProtection);
 
-  /// Get the EEPROM Emulation Mode status.
+  /// @brief Get the EEPROM Emulation Mode status.
   /// @returns True if EEPROM Emulation Mode is enabled.
   bool eepromEmulation() const {
     return ((status & eepromEmulationMask) == eepromEmulationMask);
@@ -467,7 +486,7 @@
   MaximInterface_EXPORT BlockProtection &
   setEepromEmulation(bool eepromEmulation);
 
-  /// Get the Authentication Protection status.
+  /// @brief Get the Authentication Protection status.
   /// @returns True if Authentication Protection is enabled.
   bool authProtection() const {
     return ((status & authProtectionMask) == authProtectionMask);
@@ -477,7 +496,7 @@
   MaximInterface_EXPORT BlockProtection &
   setAuthProtection(bool authProtection);
 
-  /// Check if no protection options are enabled.
+  /// @brief Check if no protection options are enabled.
   /// @returns True if no protection options are enabled.
   MaximInterface_EXPORT bool noProtection() const;
 
@@ -500,6 +519,7 @@
   return !operator==(lhs, rhs);
 }
 
+/// Format data to hash for an Authenticated Write to a memory segment.
 class DS28E15_22_25::SegmentWriteMacData {
 public:
   SegmentWriteMacData() : result_() {}
@@ -507,88 +527,122 @@
   /// Formatted data result.
   Sha256::WriteMacData::const_span result() const { return result_; }
 
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
   /// @{
-  /// 1-Wire ROM ID of the device.
+
+  /// Get mutable ROM ID.
   RomId::span romId() {
     return make_span(result_).subspan<romIdIdx, RomId::size>();
   }
   
+  /// Get immutable ROM ID.
   RomId::const_span romId() const {
     return const_cast<SegmentWriteMacData &>(*this).romId();
   }
   
+  /// Set ROM ID.
   SegmentWriteMacData & setRomId(RomId::const_span romId) {
     copy(romId, this->romId());
     return *this;
   }
+  
   /// @}
 
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
   /// @{
-  /// Manufacturer ID of the device.
+  
+  /// Get mutable MAN ID.
   ManId::span manId() {
     return make_span(result_).subspan<manIdIdx, ManId::size>();
   }
   
+  /// Get immutable MAN ID.
   ManId::const_span manId() const {
     return const_cast<SegmentWriteMacData &>(*this).manId();
   }
   
+  /// Set MAN ID.
   SegmentWriteMacData & setManId(ManId::const_span manId) {
     copy(manId, this->manId());
     return *this;
   }
+  
   /// @}
 
+  /// @name Page number
+  /// @brief Page number for write operation.
   /// @{
-  /// Page number for write operation.
+
+  /// Get page number.
   int pageNum() const { return result_[pageNumIdx]; }
   
+  /// Set page number.
   SegmentWriteMacData & setPageNum(int pageNum) {
     result_[pageNumIdx] = pageNum;
     return *this;
   }
+  
   /// @}
 
+  /// @name Segment number
+  /// @brief Segment number within page for write operation.
   /// @{
-  /// Segment number within page for write operation.
+  
+  /// Get segment number.
   int segmentNum() const { return result_[segmentNumIdx]; }
   
+  /// Set segment number.
   SegmentWriteMacData & setSegmentNum(int segmentNum) {
     result_[segmentNumIdx] = segmentNum;
     return *this;
   }
+  
   /// @}
 
+  /// @name Old data
+  /// @brief Existing data contained in the segment.
   /// @{
-  /// Existing data contained in the segment.
+  
+  /// Get mutable old data.
   Segment::span oldData() {
     return make_span(result_).subspan<oldDataIdx, Segment::size>();
   }
   
+  /// Get immutable old data.
   Segment::const_span oldData() const {
     return const_cast<SegmentWriteMacData &>(*this).oldData();
   }
   
+  /// Set old data.
   SegmentWriteMacData & setOldData(Segment::const_span oldData) {
     copy(oldData, this->oldData());
     return *this;
   }
+  
   /// @}
 
+  /// @name New data
+  /// @brief New data to write to the segment.
   /// @{
-  /// New data to write to the segment.
+  
+  /// Get mutable new data.
   Segment::span newData() {
     return make_span(result_).subspan<newDataIdx, Segment::size>();
   }
   
+  /// Get immutable new data.
   Segment::const_span newData() const {
     return const_cast<SegmentWriteMacData &>(*this).newData();
   }
   
+  /// Set new data.
   SegmentWriteMacData & setNewData(Segment::const_span newData) {
     copy(newData, this->newData());
     return *this;
   }
+  
   /// @}
 
 private:
@@ -604,6 +658,7 @@
   Sha256::WriteMacData::array result_;
 };
 
+/// Format data to hash for an Authenticated Write to a memory protection block.
 class DS28E15_22_25::ProtectionWriteMacData {
 public:
   MaximInterface_EXPORT ProtectionWriteMacData();
@@ -611,52 +666,74 @@
   /// Formatted data result.
   Sha256::WriteMacData::const_span result() const { return result_; }
 
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
   /// @{
-  /// 1-Wire ROM ID of the device.
+  
+  /// Get mutable ROM ID.
   RomId::span romId() {
     return make_span(result_).subspan<romIdIdx, RomId::size>();
   }
   
+  /// Get immutable ROM ID.
   RomId::const_span romId() const {
     return const_cast<ProtectionWriteMacData &>(*this).romId();
   }
   
+  /// Set ROM ID.
   ProtectionWriteMacData & setRomId(RomId::const_span romId) {
     copy(romId, this->romId());
     return *this;
   }
+  
   /// @}
 
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
   /// @{
-  /// Manufacturer ID of the device.
+  
+  /// Get mutable MAN ID.
   ManId::span manId() {
     return make_span(result_).subspan<manIdIdx, ManId::size>();
   }
   
+  /// Get immutable MAN ID.
   ManId::const_span manId() const {
     return const_cast<ProtectionWriteMacData &>(*this).manId();
   }
   
+  /// Set MAN ID.
   ProtectionWriteMacData & setManId(ManId::const_span manId) {
     copy(manId, this->manId());
     return *this;
   }
+  
   /// @}
 
+  /// @name Old protection
+  /// @brief Existing protection status in device.
   /// @{
-  /// Existing protection status in device.
+  
+  /// Get old protection.
   BlockProtection oldProtection() const { return oldProtection_; }
   
+  /// Set old protection.
   MaximInterface_EXPORT ProtectionWriteMacData &
   setOldProtection(BlockProtection oldProtection);
+  
   /// @}
 
+  /// @name New protection
+  /// @brief New protection status to write.
   /// @{
-  /// New protection status to write.
+  
+  /// Get new protection.
   BlockProtection newProtection() const { return newProtection_; }
   
+  /// Set new protection.
   MaximInterface_EXPORT ProtectionWriteMacData &
   setNewProtection(BlockProtection newProtection);
+  
   /// @}
 
 private:
@@ -673,6 +750,9 @@
   BlockProtection newProtection_;
 };
 
+/// @brief
+/// Format data to hash for device authentication or computing the next secret
+/// from the existing secret.
 class DS28E15_22_25::AuthenticationData {
 public:
   AuthenticationData() : result_() {}
@@ -680,81 +760,112 @@
   /// Formatted data result.
   Sha256::AuthenticationData::const_span result() const { return result_; }
 
+  /// @name Page
+  /// @brief Data from a device memory page.
   /// @{
-  /// Data from a device memory page.
+  
+  /// Get mutable page.
   Page::span page() {
     return make_span(result_).subspan<pageIdx, Page::size>();
   }
   
+  /// Get immutable page.
   Page::const_span page() const {
     return const_cast<AuthenticationData &>(*this).page();
   }
   
+  /// Set page.
   AuthenticationData & setPage(Page::const_span page) {
     copy(page, this->page());
     return *this;
   }
+  
   /// @}
 
-  /// @{
+  /// @name Scratchpad
+  /// @brief
   /// Data from device scratchpad used as a random challenge in device
   /// authentication and a partial secret in secret computation.
+  /// @{
+
+  /// Get mutable scratchpad.
   Scratchpad::span scratchpad() {
     return make_span(result_).subspan<scratchpadIdx, Scratchpad::size>();
   }
   
+  /// Get immutable scratchpad.
   Scratchpad::const_span scratchpad() const {
     return const_cast<AuthenticationData &>(*this).scratchpad();
   }
   
+  /// Set scratchpad.
   AuthenticationData & setScratchpad(Scratchpad::const_span scratchpad) {
     copy(scratchpad, this->scratchpad());
     return *this;
   }
+  
   /// @}
 
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
   /// @{
-  /// 1-Wire ROM ID of the device.
+  
+  /// Get mutable ROM ID.
   RomId::span romId() {
     return make_span(result_).subspan<romIdIdx, RomId::size>();
   }
   
+  /// Get immutable ROM ID.
   RomId::const_span romId() const {
     return const_cast<AuthenticationData &>(*this).romId();
   }
   
+  /// Set ROM ID.
   AuthenticationData & setRomId(RomId::const_span romId) {
     copy(romId, this->romId());
     return *this;
   }
   
+  /// Set ROM ID for use in anonymous mode.
   MaximInterface_EXPORT AuthenticationData & setAnonymousRomId();
+  
   /// @}
 
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
   /// @{
-  /// Manufacturer ID of the device.
+  
+  /// Get mutable MAN ID.
   ManId::span manId() {
     return make_span(result_).subspan<manIdIdx, ManId::size>();
   }
   
+  /// Get immutable MAN ID.
   ManId::const_span manId() const {
     return const_cast<AuthenticationData &>(*this).manId();
   }
   
+  /// Set MAN ID.
   AuthenticationData & setManId(ManId::const_span manId) {
     copy(manId, this->manId());
     return *this;
   }
+  
   /// @}
 
+  /// @name Page number
+  /// @brief Number of the page to use data from.
   /// @{
-  /// Number of the page to use data from.
+  
+  /// Get page number.
   int pageNum() const { return result_[pageNumIdx]; }
   
+  /// Set page number.
   AuthenticationData & setPageNum(int pageNum) {
     result_[pageNumIdx] = pageNum;
     return *this;
   }
+  
   /// @}
 
 private:
--- a/Devices/DS28E17.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Devices/DS28E17.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -40,7 +40,7 @@
 
 namespace MaximInterface {
 
-/// DS28E17 1-Wire®-to-I2C Master Bridge
+/// @brief DS28E17 1-Wire®-to-I2C Master Bridge
 /// @details The DS28E17 is a 1-Wire slave to I2C master bridge
 /// device that interfaces directly to I2C slaves at standard
 /// (100kHz max) or fast (400kHz max). Data transfers serially by
@@ -75,7 +75,7 @@
     this->selectRom = selectRom;
   }
 
-  /// Write Data With Stop command.
+  /// @brief Write Data With Stop command.
   /// @details Output on I2C: S, Address + Write, Write Data [1-255], P
   /// @param[in] I2C_addr
   /// I2C slave address. The least significant bit of the I2C
@@ -89,7 +89,7 @@
   writeDataWithStop(uint_least8_t I2C_addr, span<const uint_least8_t> data,
                     uint_least8_t * wr_status = NULL);
 
-  /// Write Data No Stop command.
+  /// @brief Write Data No Stop command.
   /// @details Output on I2C: S, Address + Write, Write Data [1-255]
   /// @param[in] I2C_addr
   /// I2C slave address. The least significant bit of the I2C address
@@ -103,7 +103,7 @@
   writeDataNoStop(uint_least8_t I2C_addr, span<const uint_least8_t> data,
                   uint_least8_t * wr_status = NULL);
 
-  /// Write Data Only command.
+  /// @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
@@ -114,7 +114,7 @@
   writeDataOnly(span<const uint_least8_t> data,
                 uint_least8_t * wr_status = NULL);
 
-  /// Write Data Only With Stop command.
+  /// @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
@@ -125,7 +125,7 @@
   writeDataOnlyWithStop(span<const uint_least8_t> data,
                         uint_least8_t * wr_status = NULL);
 
-  /// Write, Read Data With Stop command.
+  /// @brief Write, Read Data With Stop command.
   /// @details Output on I2C:
   /// S, Slave Address + Write, Write Data [1-255],
   /// Sr, Address + Read, Read Data [1-255], P (NACK last read byte)
@@ -142,7 +142,7 @@
       uint_least8_t I2C_addr, span<const uint_least8_t> write_data,
       span<uint_least8_t> read_data, uint_least8_t * wr_status = NULL);
 
-  /// Read Data With Stop command.
+  /// @brief Read Data With Stop command.
   /// @details Output on I2C:
   /// S, Slave Address + Read, Read Data [1-255], P (NACK last read byte)
   /// @param[in]  I2C_addr
@@ -155,17 +155,17 @@
   /// Write to Configuration Register of DS28E17.
   MaximInterface_EXPORT error_code writeConfigReg(I2CSpeed speed);
 
-  /// Read the Configuration Register of DS28E17.
+  /// @brief Read the Configuration Register of DS28E17.
   /// @param[out] speed Speed read from configuration register.
   MaximInterface_EXPORT error_code readConfigReg(I2CSpeed & speed);
 
-  /// The Enable Sleep Mode command puts the device into a low current mode.
+  /// @brief Put the device into a low current mode.
   /// @details All 1-Wire communication is ignored until woken up. Immediately
   /// after the command, the device monitors the WAKEUP input pin and exits
   /// sleep mode on a rising edge.
   MaximInterface_EXPORT error_code enableSleepMode();
 
-  /// Read the Device Revision of DS28E17.
+  /// @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.
--- a/Devices/DS28E38.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Devices/DS28E38.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -57,18 +57,22 @@
         0x100 ///< Command response does not match expected format.
   };
 
-  // Device memory pages.
+  /// @name Device memory pages
+  /// @{
+  
   static const int decrementCounterPage = 3;
   static const int publicKeyXPage = 4;
   static const int publicKeyYPage = 5;
   static const int privateKeyPage = 6;
+  
+  /// @}
 
   static const int memoryPages = 7;
 
   /// Holds a device memory page.
   typedef array_span<uint_least8_t, 32> Page;
 
-  /// Format page authentication input data.
+  // Format page authentication input data.
   class PageAuthenticationData;
 
   /// Page protection types.
@@ -103,17 +107,18 @@
     doRunCommand = runCommand;
   }
 
-  /// Write memory with no protection.
+  /// @brief Write memory with no protection.
   /// @param pageNum Number of page to write.
   /// @param page Data to write.
   MaximInterface_EXPORT error_code writeMemory(int pageNum,
                                                Page::const_span page);
 
-  /// Read memory with no protection.
+  /// @brief Read memory with no protection.
   /// @param pageNum Number of page to read.
   /// @param[out] page Data that was read.
   MaximInterface_EXPORT error_code readMemory(int pageNum, Page::span page);
 
+  /// @brief
   /// Reads the current status of the device and optionally performs an
   /// entropy health test.
   /// @param entropyHealthTest True to perform an entropy health test.
@@ -121,13 +126,13 @@
   MaximInterface_EXPORT error_code readStatus(bool entropyHealthTest,
                                               Status & status);
 
-  /// Set the protection settings of a page.
+  /// @brief Set the protection settings of a page.
   /// @param pageNum Number of page to write.
   /// @param protection Protection to write.
   MaximInterface_EXPORT error_code
   setPageProtection(int pageNum, const PageProtection & protection);
 
-  /// Compute and read page authentication with ECDSA.
+  /// @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.
@@ -142,13 +147,13 @@
   /// Permanently disable the device.
   MaximInterface_EXPORT error_code disableDevice();
 
-  /// Generate a new ECDSA public key from an existing private key.
+  /// @brief Generate a new ECDSA public key from an existing private key.
   /// @param privateKeyPuf True if PUF is used as the private key.
   /// @param writeProtectEnable True to lock the key against further writes.
   MaximInterface_EXPORT error_code
   generateEcc256KeyPair(bool privateKeyPuf, bool writeProtectEnable);
 
-  /// Read a block of random data from the RNG.
+  /// @brief Read a block of random data from the RNG.
   /// @param[out] data Random data from RNG with length from 1 to 64.
   MaximInterface_EXPORT error_code readRng(span<uint_least8_t> data);
 
@@ -170,12 +175,13 @@
   return error_code(e, DS28E38::errorCategory());
 }
 
-/// Read the device MAN ID using the Read Status command.
+/// @brief Read the device MAN ID using the Read Status command.
 /// @param ds28e38 Device to read.
 /// @param[out] manId Read MAN ID valid when operation is successful.
 MaximInterface_EXPORT error_code readManId(DS28E38 & ds28e38,
                                            ManId::span manId);
 
+/// Format page authentication input data.
 class DS28E38::PageAuthenticationData {
 public:
   typedef array_span<uint_least8_t,
@@ -187,80 +193,110 @@
   /// Formatted data result.
   Result::const_span result() const { return result_; }
 
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
   /// @{
-  /// 1-Wire ROM ID of the device.
+  
+  /// Get mutable ROM ID.
   RomId::span romId() {
     return make_span(result_).subspan<romIdIdx, RomId::size>();
   }
   
+  /// Get immutable ROM ID.
   RomId::const_span romId() const {
     return const_cast<PageAuthenticationData &>(*this).romId();
   }
   
+  /// Set ROM ID.
   PageAuthenticationData & setRomId(RomId::const_span romId) {
     copy(romId, this->romId());
     return *this;
   }
   
+  /// Set ROM ID for use in anonymous mode.
   MaximInterface_EXPORT PageAuthenticationData & setAnonymousRomId();
+  
   /// @}
 
+  /// @name Page
+  /// @brief Data from a device memory page.
   /// @{
-  /// Data from a device memory page.
+  
+  /// Get mutable page.
   Page::span page() {
     return make_span(result_).subspan<pageIdx, Page::size>();
   }
   
+  /// Get immutable page.
   Page::const_span page() const {
     return const_cast<PageAuthenticationData &>(*this).page();
   }
   
+  /// Set page.
   PageAuthenticationData & setPage(Page::const_span page) {
     copy(page, this->page());
     return *this;
   }
+  
   /// @}
 
+  /// @name Challenge
+  /// @brief Random challenge used to prevent replay attacks.
   /// @{
-  /// Random challenge used to prevent replay attacks.
+
+  /// Get mutable Challenge.
   Page::span challenge() {
     return make_span(result_).subspan<challengeIdx, Page::size>();
   }
   
+  /// Get immutable Challenge.
   Page::const_span challenge() const {
     return const_cast<PageAuthenticationData &>(*this).challenge();
   }
   
+  /// Set Challenge.
   PageAuthenticationData & setChallenge(Page::const_span challenge) {
     copy(challenge, this->challenge());
     return *this;
   }
+  
   /// @}
 
+  /// @name Page number
+  /// @brief Number of the page to use data from.
   /// @{
-  /// Number of the page to use data from.
+  
+  /// Get page number.
   int pageNum() const { return result_[pageNumIdx]; }
   
+  /// Set page number.
   PageAuthenticationData & setPageNum(int pageNum) {
     result_[pageNumIdx] = pageNum;
     return *this;
   }
+  
   /// @}
 
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
   /// @{
-  /// Manufacturer ID of the device.
+  
+  /// Get mutable MAN ID.
   ManId::span manId() {
     return make_span(result_).subspan<manIdIdx, ManId::size>();
   }
   
+  /// Get immutable MAN ID.
   ManId::const_span manId() const {
     return const_cast<PageAuthenticationData &>(*this).manId();
   }
   
+  /// Set MAN ID.
   PageAuthenticationData & setManId(ManId::const_span manId) {
     copy(manId, this->manId());
     return *this;
   }
+  
   /// @}
 
 private:
--- a/Links/I2CMaster.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Links/I2CMaster.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -51,7 +51,7 @@
 
   virtual ~I2CMaster() {}
 
-  /// Send start condition and address on the bus.
+  /// @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;
   
@@ -65,9 +65,11 @@
   MaximInterface_EXPORT virtual error_code
   writeBlock(span<const uint_least8_t> data);
   
+  /// @brief
   /// Perform a complete write transaction on the bus with optional stop
   /// condition.
   /// @param address Address in 8-bit format.
+  /// @param data Data to write to the bus.
   /// @param sendStop
   /// True to send a stop condition or false to set up a repeated start.
   error_code writePacket(uint_least8_t address, span<const uint_least8_t> data,
@@ -75,20 +77,22 @@
     return writePacketImpl(address, data, sendStop);
   }
   
-  /// Read data byte from the bus.
+  /// @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;
   
-  /// Read data block from the bus.
+  /// @brief Read data block from the bus.
   /// @param status Determines whether an ACK or NACK is sent after reading.
   /// @param[out] data Data read from the bus if successful.
   MaximInterface_EXPORT virtual error_code
   readBlock(AckStatus status, span<uint_least8_t> data);
   
+  /// @brief
   /// Perform a complete read transaction on the bus with optional stop
   /// condition.
   /// @param address Address in 8-bit format.
+  /// @param[out] data Data read from the bus if successful.
   /// @param sendStop
   /// True to send a stop condition or false to set up a repeated start.
   error_code readPacket(uint_least8_t address, span<uint_least8_t> data,
--- a/Links/OneWireMaster.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Links/OneWireMaster.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -65,10 +65,13 @@
 
   virtual ~OneWireMaster() {}
 
+  /// @brief
   /// Reset all of the devices on the 1-Wire bus and check for a presence pulse.
-  /// @returns NoSlaveError if reset was performed but no presence pulse was detected.
+  /// @returns
+  /// NoSlaveError if reset was performed but no presence pulse was detected.
   virtual error_code reset() = 0;
 
+  /// @brief
   /// Send and receive one bit of communication and set a new level on the
   /// 1-Wire bus.
   /// @param[in,out] sendRecvBit
@@ -76,24 +79,26 @@
   /// @param afterLevel Level to set the 1-Wire bus to after communication.
   virtual error_code touchBitSetLevel(bool & sendRecvBit, Level afterLevel) = 0;
 
+  /// @brief
   /// Send one byte of communication and set a new level on the 1-Wire bus.
   /// @param sendByte Byte to send on the 1-Wire bus.
   /// @param afterLevel Level to set the 1-Wire bus to after communication.
   MaximInterface_EXPORT virtual error_code
   writeByteSetLevel(uint_least8_t sendByte, Level afterLevel);
 
+  /// @brief
   /// Receive one byte of communication and set a new level on the 1-Wire bus.
   /// @param recvByte Buffer to receive the data from the 1-Wire bus.
   /// @param afterLevel Level to set the 1-Wire bus to after communication.
   MaximInterface_EXPORT virtual error_code
   readByteSetLevel(uint_least8_t & recvByte, Level afterLevel);
 
-  /// Send a block of communication on the 1-Wire bus.
+  /// @brief Send a block of communication on the 1-Wire bus.
   /// @param[in] sendBuf Buffer to send on the 1-Wire bus.
   MaximInterface_EXPORT virtual error_code
   writeBlock(span<const uint_least8_t> sendBuf);
 
-  /// Receive a block of communication on the 1-Wire bus.
+  /// @brief Receive a block of communication on the 1-Wire bus.
   /// @param[out] recvBuf Buffer to receive the data from the 1-Wire bus.
   MaximInterface_EXPORT virtual error_code
   readBlock(span<uint_least8_t> recvBuf);
@@ -104,16 +109,17 @@
   /// Set the 1-Wire bus level.
   virtual error_code setLevel(Level newLevel) = 0;
 
-  /// 1-Wire Triplet operation.
+  /// @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
+  /// @param[in,out] data
   /// Input with desired writeBit in case both read bits are zero.
   /// Output with all data fields set.
   MaximInterface_EXPORT virtual error_code triplet(TripletData & data);
 
+  /// @brief
   /// Send one bit of communication and set a new level on the 1-Wire bus.
   /// @param sendBit Bit to send on the 1-Wire bus.
   /// @param afterLevel Level to set the 1-Wire bus to after communication.
@@ -121,6 +127,7 @@
     return touchBitSetLevel(sendBit, afterLevel);
   }
 
+  /// @brief
   /// Receive one bit of communication and set a new level on the 1-Wire bus.
   /// @param[out] recvBit Received data from the 1-Wire bus.
   /// @param afterLevel Level to set the 1-Wire bus to after communication.
--- a/Links/RomCommands.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Links/RomCommands.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -31,7 +31,7 @@
 *******************************************************************************/
 
 /// @file
-/// ROM Commands for enumerating and selecting 1-Wire devices.
+/// @brief ROM Commands for enumerating and selecting 1-Wire devices.
 
 #ifndef MaximInterface_RomCommands
 #define MaximInterface_RomCommands
@@ -66,6 +66,7 @@
   }
 };
 
+/// @brief
 /// Set the search state to skip the current device family on the next
 /// Search ROM command.
 MaximInterface_EXPORT void skipCurrentFamily(SearchRomState & searchState);
@@ -74,43 +75,53 @@
 MaximInterface_EXPORT error_code verifyRom(OneWireMaster & master,
                                            RomId::const_span romId);
 
-/// Use Read ROM command to read ROM ID from device on bus.
-/// @note Only use this command with a single drop bus, data
-///       collisions will occur if more than 1 device on bus.
+/// @brief Use Read ROM command to read ROM ID from device on bus.
+/// @note
+/// Only use this command with a single-drop bus.
+/// Data collisions will occur if there is more than one device on the bus.
+/// @param master 1-Wire master for operation.
 /// @param[out] romId ROM ID read from device.
 MaximInterface_EXPORT error_code readRom(OneWireMaster & master,
                                          RomId::span romId);
 
-/// Issue Skip ROM command on bus.
-/// @note Only use this command with a single drop bus, data
-///       collisions will occur if more than 1 device on bus.
+/// @brief Issue Skip ROM command on bus.
+/// @note
+/// Only use this command with a single-drop bus.
+/// Data collisions will occur if there is more than one device on the bus.
 MaximInterface_EXPORT error_code skipRom(OneWireMaster & master);
 
-/// Use the Match ROM command to select the device by its known ID.
-/// @note This command causes all devices supporting Overdrive
-///       mode to switch to Overdrive timing.
+/// @brief Use the Match ROM command to select the device by its known ID.
+/// @note
+/// This command causes all devices supporting Overdrive mode to switch to
+/// Overdrive timing.
+/// @param master 1-Wire master for operation.
 /// @param[in] romId ROM ID of device to select.
 MaximInterface_EXPORT error_code matchRom(OneWireMaster & master,
                                           RomId::const_span romId);
 
-/// Issue Overdrive Skip ROM command on bus.
-/// @note This command causes all devices supporting Overdrive
-///       mode to switch to Overdrive timing.
-/// @note Only use this command with a single drop bus, data
-///       collisions will occur if more than 1 device on bus.
+/// @brief Issue Overdrive Skip ROM command on bus.
+/// @note
+/// This command causes all devices supporting Overdrive mode to switch to
+/// Overdrive timing.
+/// @note
+/// Only use this command with a single-drop bus.
+/// Data collisions will occur if there is more than one device on the bus.
 MaximInterface_EXPORT error_code overdriveSkipRom(OneWireMaster & master);
 
+/// @brief
 /// Use the Overdrive Match ROM command to select the device by its known ID.
+/// @param master 1-Wire master for operation.
 /// @param[in] romId ROM ID of device to select.
 MaximInterface_EXPORT error_code overdriveMatchRom(OneWireMaster & master,
                                                    RomId::const_span romId);
 
-/// Perform a Resume ROM command on bus.
-/// @details Resumes communication with the last device selected
-///          though a Match ROM or Search ROM operation.
+/// @brief Perform a Resume ROM command on bus.
+/// @details
+/// Resumes communication with the last device selected through a Match ROM or
+/// Search ROM operation.
 MaximInterface_EXPORT error_code resumeRom(OneWireMaster & master);
 
-/// Find device on the 1-Wire bus.
+/// @brief Find device on the 1-Wire bus.
 /// @details
 /// This command uses the Search ROM command to enumerate all 1-Wire devices in
 /// sequence. Begin with a new search state and continue using the same search
--- a/Links/SelectRom.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Links/SelectRom.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -64,6 +64,7 @@
   RomId::array romId_;
 };
 
+/// @brief
 /// Selector for a multidrop 1-Wire bus where slaves support the Resume ROM
 /// command.
 class SelectMatchRomWithResume {
--- a/Links/SerialPort.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Links/SerialPort.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -46,7 +46,7 @@
   /// Disconnect from the current port.
   virtual error_code disconnect() = 0;
   
-  /// Check if currently connected to a port.
+  /// @brief Check if currently connected to a port.
   /// @returns True if connected.
   virtual bool connected() const = 0;
 
--- a/Links/Uart.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Links/Uart.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -66,11 +66,13 @@
   MaximInterface_EXPORT virtual error_code
   writeBlock(span<const uint_least8_t> data);
   
+  /// @brief
   /// Reads a byte of data from the port. Block until data is received or a
   /// timeout is reached.
   /// @param[out] data Data read from the port if successful.
   virtual error_code readByte(uint_least8_t & data) = 0;
   
+  /// @brief
   /// Read a block of data from the port. Block until data is received or a
   /// timeout is reached.
   /// @param[out] data Data read from the port if successful.
--- a/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/owlink.h	Wed Jan 23 13:11:04 2019 -0600
+++ b/Platforms/mbed/TARGET_Maxim/TARGET_MAX32600/owlink.h	Mon Mar 04 08:10:00 2019 -0600
@@ -39,8 +39,7 @@
 extern "C" {
 #endif
 
-/// Timing parameters for the 1-Wire bus.
-/// @note All times are in terms of microseconds.
+/// Timing parameters for the 1-Wire bus in microseconds.
 struct OneWireTiming {
   uint16_t tRSTL; ///< Reset Low Time
   uint16_t tMSP;  ///< Presence-Detect Sample Time
@@ -53,10 +52,11 @@
 /// Delay for the specified number of microseconds.
 void ow_usdelay(unsigned int time_us);
 
-/// Send and receive one bit of communication and set a new level on the 1-Wire bus.
+/// @brief Send and receive one bit, and set a new level on the 1-Wire bus.
 /// @note GPIO pin must be configured for open drain operation.
-/// @param[in,out] sendRecvBit Buffer containing the bit to send on 1-Wire bus in lsb.
-///                            Read data from 1-Wire bus will be returned in lsb.
+/// @param[in,out] sendRecvBit
+/// Buffer containing the bit to send on 1-Wire bus in lsb.
+/// Read data from 1-Wire bus will be returned in lsb.
 /// @param[in] inReg Input register for GPIO pin.
 /// @param[in,out] outReg Output register for GPIO pin.
 /// @param pinMask Pin mask for input and output registers.
--- a/Utilities/ChangeSizeType.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Utilities/ChangeSizeType.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -41,9 +41,14 @@
 
 namespace MaximInterface {
 
-/// Adapts functions taking a data pointer and data size where the size type is
-/// nonstandard. The function will be called multiple times if necessary to
-/// process all data.
+/// @brief
+/// Adapts functions taking an array pointer and size where the size type is
+/// nonstandard.
+/// @tparam NewSize Nonstandard size type.
+/// @tparam Func Must be callable as func(Data *, NewSize).
+/// @tparam Data Array element type.
+/// @param func Callback for processing chunks of data.
+/// @param data Data to process with callback.
 template <typename NewSize, typename Func, typename Data>
 error_code changeSizeType(Func func, span<Data> data) {
   using namespace std;
--- a/Utilities/Ecc256.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Utilities/Ecc256.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -169,49 +169,68 @@
   /// Formatted data result.
   Result::const_span result() const { return result_; }
 
+  /// @name Public Key
+  /// @brief Public key of the device.
   /// @{
-  /// Public key of the device.
+  
+  /// Get mutable Public Key.
   MaximInterface_EXPORT PublicKey::span publicKey();
+  
+  /// Get immutable Public Key.
   PublicKey::const_span publicKey() const {
     return const_cast<CertificateData &>(*this).publicKey();
   }
   
+  /// Set Public Key.
   CertificateData & setPublicKey(PublicKey::const_span publicKey) {
     copy(publicKey, this->publicKey());
     return *this;
   }
+  
   /// @}
 
+  /// @name ROM ID
+  /// @brief 1-Wire ROM ID of the device.
   /// @{
-  /// 1-Wire ROM ID of the device.
+  
+  /// Get mutable ROM ID.
   RomId::span romId() {
     return make_span(result_).subspan<romIdIdx, RomId::size>();
   }
   
+  /// Get immutable ROM ID.
   RomId::const_span romId() const {
     return const_cast<CertificateData &>(*this).romId();
   }
   
+  /// Set ROM ID.
   CertificateData & setRomId(RomId::const_span romId) {
     copy(romId, this->romId());
     return *this;
   }
+  
   /// @}
 
+  /// @name MAN ID
+  /// @brief Manufacturer ID of the device.
   /// @{
-  /// Manufacturer ID of the device.
+  
+  /// Get mutable MAN ID.
   ManId::span manId() {
     return make_span(result_).subspan<manIdIdx, ManId::size>();
   }
   
+  /// Get immutable MAN ID.
   ManId::const_span manId() const {
     return const_cast<CertificateData &>(*this).manId();
   }
   
+  /// Set MAN ID.
   CertificateData & setManId(ManId::const_span manId) {
     copy(manId, this->manId());
     return *this;
   }
+  
   /// @}
 
 private:
--- a/Utilities/Error.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Utilities/Error.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -37,8 +37,8 @@
 
 namespace MaximInterface {
 
-/// Get the default error message associated with a condition. Typically used
-/// by an error_category when the condition is unknown.
+/// @brief Get the default error message associated with a condition.
+/// @details Typically used by an error_category when the condition is unknown.
 MaximInterface_EXPORT const char * defaultErrorMessage(int condition);
 
 }
--- a/Utilities/FlagSet.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Utilities/FlagSet.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -38,6 +38,7 @@
 
 namespace MaximInterface {
 
+/// @brief
 /// Provides functionality similar to std::bitset except using a bit flag,
 /// typically of an enum type, as the indexer.
 template <typename Flag, size_t flagBits> class FlagSet {
@@ -87,6 +88,7 @@
 
   /// @name Element access
   /// @{
+  
   bool operator[](Flag flag) const { return test(flag); }
   
   reference operator[](Flag flag) { return reference(*this, flag); }
@@ -98,15 +100,19 @@
   bool none() const { return bits.none(); }
   
   size_t count() const { return bits.count(); }
+  
   /// @}
 
   /// @name Capacity
   /// @{
+  
   size_t size() const { return bits.size(); }
+  
   /// @}
 
   /// @name Modifiers
   /// @{
+  
   FlagSet & operator&=(const FlagSet & other) {
     bits &= other.bits;
     return *this;
@@ -154,16 +160,19 @@
     bits ^= flag;
     return *this;
   }
+  
   /// @}
 
   /// @name Conversions
   /// @{
+  
   template <typename CharT, typename Traits, typename Allocator>
   std::basic_string<CharT, Traits, Allocator> to_string() const {
     return bits.template to_string<CharT, Traits, Allocator>();
   }
   
   unsigned long to_ulong() const { return bits.to_ulong(); }
+  
   /// @}
 
 private:
--- a/Utilities/Function.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Utilities/Function.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -240,7 +240,7 @@
 
 } // namespace detail
 
-// Function wrapper similar to std::function for 0-2 argument functions.
+// Function wrapper similar to std::function for 0-3 argument functions.
 template <typename> class Function;
 
 // Function implementation for zero argument functions.
--- a/Utilities/RomId.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Utilities/RomId.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -41,29 +41,37 @@
 /// Standard container for a 1-Wire ROM ID.
 typedef array_span<uint_least8_t, 8> RomId;
 
+/// @name Family Code
 /// @{
-/// Access the Family Code byte.
+
+/// 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
 /// @{
-/// Access the CRC8 byte.
+
+/// 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;
 }
+
 /// @}
 
-/// Check if the ROM ID is valid (Family Code and CRC8 are both valid).
+/// @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);
--- a/Utilities/SafeBool.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Utilities/SafeBool.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -49,6 +49,8 @@
 
 } // namespace detail
 
+/// @brief Type definition for SafeBool.
+/// @details
 /// SafeBool is a boolean type that eliminates many error-prone implicit
 /// conversions allowed by the fundamental bool type.
 /// @note
--- a/Utilities/Segment.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Utilities/Segment.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -39,8 +39,9 @@
 
 namespace MaximInterface {
 
+/// @brief
 /// Advances a given iterator by a given number of elements with bounds checking.
-/// InputIt must meet the requirements of InputIterator.
+/// @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
@@ -97,14 +98,17 @@
   return distance;
 }
 
-/// Locates an iterator sub-range using segment number addressing. Useful for
-/// devices that divide the memory space into uniform chunks such as pages and
-/// segments. ForwardIt must meet the requirements of ForwardIterator.
+/// @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
+/// @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>
--- a/Utilities/Sha256.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Utilities/Sha256.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -42,12 +42,12 @@
 /// Container for a SHA-256 hash.
 typedef array_span<uint_least8_t, 32> Hash;
 
-/// Data for Compute Write MAC operation.
+/// @brief Data for Compute Write MAC operation.
 /// @details
 /// Used by SHA-256 MAC authenticators including DS28E15/22/25 and DS2465.
 typedef array_span<uint_least8_t, 20> WriteMacData;
 
-/// Data for the Compute Auth. MAC and Compute Slave Secret operations.
+/// @brief Data for the Compute Auth. MAC and Compute Slave Secret operations.
 /// @copydetails WriteMacData
 typedef array_span<uint_least8_t, 76> AuthenticationData;
 
--- a/Utilities/array.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Utilities/array.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -57,6 +57,7 @@
 
   /// @name Element access
   /// @{
+  
   reference operator[](size_type pos) {
     return const_cast<reference>(
         static_cast<const array &>(*this).operator[](pos));
@@ -81,10 +82,12 @@
   }
   
   const_pointer data() const { return _buffer; }
+  
   /// @}
 
   /// @name Iterators
-  /// @{  
+  /// @{
+  
   iterator begin() {
     return const_cast<iterator>(static_cast<const array &>(*this).cbegin());
   }
@@ -116,10 +119,12 @@
   }
   
   const_reverse_iterator crend() const { return rend(); }
+  
   /// @}
 
   /// @name Capacity
   /// @{
+  
   static bool empty() { return size() == 0; }
   
   static size_type size() { return N; }
@@ -128,17 +133,20 @@
   
   /// Alternative to size() when a constant expression is required.
   static const size_type csize = N;
+  
   /// @}
 
   /// @name Operations
   /// @{
+  
   void fill(const_reference value) { std::fill(begin(), end(), value); }
   
   void swap(array & other) { std::swap_ranges(begin(), end(), other.begin()); }
+  
   /// @}
 
   /// @private
-  /// Implementation detail set public to allow aggregate initialization.
+  /// @note Implementation detail set public to allow aggregate initialization.
   T _buffer[N];
 };
 
--- a/Utilities/array_span.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Utilities/array_span.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -39,9 +39,10 @@
 
 namespace MaximInterface {
 
+/// @brief
 /// Defines a standard set of types for data fields that are represented as a
 /// fixed-size array of elements.
-/// @note A const qualifier on T is not allowed.
+/// @tparam T A const qualifier is not allowed.
 template <typename T, size_t N> struct array_span {
   typedef typename remove_volatile<T>::type element;
   static const size_t size = N;
--- a/Utilities/crc.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Utilities/crc.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -40,28 +40,28 @@
 
 namespace MaximInterface {
 
-/// Perform a CRC8 calculation.
+/// @brief Perform a CRC8 calculation.
 /// @param data Data to pass though the CRC generator.
 /// @param crc Beginning state of the CRC generator.
 /// @returns The calculated CRC8.
 MaximInterface_EXPORT uint_fast8_t calculateCrc8(uint_fast8_t data,
                                                  uint_fast8_t crc = 0);
 
-/// Perform a CRC8 calculation with variable length data.
+/// @brief Perform a CRC8 calculation with variable length data.
 /// @param[in] data Data array to pass through the CRC generator.
 /// @param crc Beginning state of the CRC generator.
 /// @returns The calculated CRC8.
 MaximInterface_EXPORT uint_fast8_t calculateCrc8(span<const uint_least8_t> data,
                                                  uint_fast8_t crc = 0);
 
-/// Perform a CRC16 calculation.
+/// @brief Perform a CRC16 calculation.
 /// @param data Data to pass though the CRC generator.
 /// @param crc Beginning state of the CRC generator.
 /// @returns The calculated CRC16.
 MaximInterface_EXPORT uint_fast16_t calculateCrc16(uint_fast8_t data,
                                                    uint_fast16_t crc = 0);
 
-/// Perform a CRC16 calculation with variable length data.
+/// @brief Perform a CRC16 calculation with variable length data.
 /// @param[in] data Data array to pass through the CRC generator.
 /// @param crc Beginning state of the CRC generator.
 /// @returns The calculated CRC16.
--- a/Utilities/optional.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Utilities/optional.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -47,7 +47,7 @@
 
 static const nullopt_t nullopt(0);
 
-/// 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.
--- a/Utilities/span.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Utilities/span.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -77,6 +77,7 @@
 public:
   /// @name Iterators
   /// @{
+  
   iterator begin() const {
     return const_cast<iterator>(static_cast<const span_base &>(*this).cbegin());
   }
@@ -100,19 +101,23 @@
   const_reverse_iterator crend() const {
     return const_reverse_iterator(cbegin());
   }
+  
   /// @}
 
   /// @name Element access
   /// @{
+  
   reference operator[](index_type idx) const { return data()[idx]; }
   
   reference operator()(index_type idx) const { return operator[](idx); }
   
   pointer data() const { return data_; }
+  
   /// @}
 
   /// @name Subviews
   /// @{
+  
   template <index_type Count> span<element_type, Count> first() const {
     return subspan<0, Count>();
   }
@@ -133,6 +138,7 @@
     return span<element_type>(
         data() + Offset, Count == dynamic_extent ? size() - Offset : Count);
   }
+  
   /// @}
 
 private:
@@ -185,18 +191,22 @@
 
   /// @name Observers
   /// @{
+  
   static index_type size() { return extent; }
   
   static index_type size_bytes() { return size() * sizeof(element_type); }
   
   static bool empty() { return size() == 0; }
+  
   /// @}
 
   /// @name Subviews
   /// @{
+  
   template <index_type Count> span<element_type, Count> last() const {
     return this->template subspan<extent - Count, Count>();
   }
+  
   /// @}
 };
 
@@ -246,18 +256,22 @@
 
   /// @name Observers
   /// @{
+  
   index_type size() const { return size_; }
   
   index_type size_bytes() const { return size() * sizeof(element_type); }
   
   bool empty() const { return size() == 0; }
+  
   /// @}
 
   /// @name Subviews
   /// @{
+  
   template <index_type Count> span<element_type, Count> last() const {
     return span<element_type, Count>(this->data() + (size() - Count), Count);
   }
+  
   /// @}
 
 private:
--- a/Utilities/system_error.hpp	Wed Jan 23 13:11:04 2019 -0600
+++ b/Utilities/system_error.hpp	Mon Mar 04 08:10:00 2019 -0600
@@ -31,8 +31,9 @@
 *******************************************************************************/
 
 /// @file
-/// Error handling constructs similar std::error_code, std::error_condition, and
-/// std::error_category.
+/// @brief
+/// Error handling constructs similar to std::error_code, std::error_condition,
+/// and std::error_category.
 
 #ifndef MaximInterface_system_error
 #define MaximInterface_system_error