Maxim Integrated / OneWire

Dependents:   MAXREFDES131_Qt_Demo MAX32630FTHR_iButton_uSD_Logger MAX32630FTHR_DS18B20_uSD_Logger MAXREFDES130_131_Demo ... more

Files at this revision

API Documentation at this revision

Comitter:
j3
Date:
Tue Dec 13 13:31:30 2016 -0800
Parent:
138:5bd0a7a82bb4
Child:
140:6f32bf635c9d
Commit message:
Merge from svn

Changed in this revision

Masters/DS2465/DS2465.cpp Show annotated file Show diff for this revision Revisions of this file
Masters/DS2465/DS2465.h Show annotated file Show diff for this revision Revisions of this file
Masters/DS248x/DS2482EightChannel/DS2482EightChannel.cpp Show annotated file Show diff for this revision Revisions of this file
Masters/DS248x/DS2482EightChannel/DS2482EightChannel.h Show annotated file Show diff for this revision Revisions of this file
Masters/DS248x/DS2482SingleChannel/DS2482SingleChannel.h Show annotated file Show diff for this revision Revisions of this file
Masters/DS248x/DS2484/DS2484.cpp Show annotated file Show diff for this revision Revisions of this file
Masters/DS248x/DS2484/DS2484.h Show annotated file Show diff for this revision Revisions of this file
Masters/DS248x/DS248x.h Show annotated file Show diff for this revision Revisions of this file
Masters/OneWireMaster.cpp Show annotated file Show diff for this revision Revisions of this file
Masters/TARGET_Maxim/TARGET_MAX32600/OwGpio/OwGpio.cpp Show annotated file Show diff for this revision Revisions of this file
Masters/TARGET_Maxim/TARGET_MAX32600/OwGpio/OwGpio.h Show annotated file Show diff for this revision Revisions of this file
Masters/TARGET_Maxim/TARGET_MAX32600/OwGpio/owlink.h Show annotated file Show diff for this revision Revisions of this file
Masters/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_ARM_STD/owlink.s Show annotated file Show diff for this revision Revisions of this file
Masters/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_GCC_ARM/owlink.S Show annotated file Show diff for this revision Revisions of this file
Masters/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_IAR/owlink.s Show annotated file Show diff for this revision Revisions of this file
RomId/RomCommands.cpp Show annotated file Show diff for this revision Revisions of this file
RomId/RomId.h Show annotated file Show diff for this revision Revisions of this file
Slaves/Authenticators/DS28E15_22_25/DS28E15.h Show annotated file Show diff for this revision Revisions of this file
Slaves/Authenticators/DS28E15_22_25/DS28E15_22_25.cpp Show annotated file Show diff for this revision Revisions of this file
Slaves/Authenticators/DS28E15_22_25/DS28E15_22_25.h Show annotated file Show diff for this revision Revisions of this file
Slaves/Authenticators/DS28E15_22_25/DS28E22.h Show annotated file Show diff for this revision Revisions of this file
Slaves/Authenticators/DS28E15_22_25/DS28E25.h Show annotated file Show diff for this revision Revisions of this file
Slaves/Bridges/DS28E17/DS28E17.h Show annotated file Show diff for this revision Revisions of this file
Slaves/Memory/DS2431/DS2431.cpp Show annotated file Show diff for this revision Revisions of this file
Utilities/array.h Show annotated file Show diff for this revision Revisions of this file
Utilities/crc.cpp Show annotated file Show diff for this revision Revisions of this file
Utilities/crc.h Show annotated file Show diff for this revision Revisions of this file
Utilities/type_traits.h Show annotated file Show diff for this revision Revisions of this file
--- a/Masters/DS2465/DS2465.cpp	Fri Dec 02 19:21:55 2016 +0000
+++ b/Masters/DS2465/DS2465.cpp	Tue Dec 13 13:31:30 2016 -0800
@@ -160,7 +160,7 @@
 ISha256MacCoproc::CmdResult DS2465::setMasterSecret(const Secret & masterSecret)
 {
     OneWireMaster::CmdResult result;
-    result = writeMemory(Scratchpad, masterSecret, masterSecret.length);
+    result = writeMemory(Scratchpad, masterSecret.data(), masterSecret.size());
     if (result == OneWireMaster::Success)
     {
         result = copyScratchpadToSecret();
@@ -176,7 +176,7 @@
 {
     OneWireMaster::CmdResult result;
     // Write input data to scratchpad
-    result = writeScratchpad(writeMacData, writeMacData.length);
+    result = writeScratchpad(writeMacData.data(), writeMacData.size());
     // Compute MAC
     if (result == OneWireMaster::Success)
     {
@@ -186,7 +186,7 @@
     {
         wait_ms(shaComputationDelayMs);
         // Read MAC from register
-        result = readMemory(MacReadoutReg, mac, mac.length, true);
+        result = readMemory(MacReadoutReg, mac.data(), mac.size(), true);
     }
     return (result == OneWireMaster::Success ? ISha256MacCoproc::Success : ISha256MacCoproc::OperationFailure);
 }
@@ -196,16 +196,16 @@
     OneWireMaster::CmdResult result;
     int addr = Scratchpad;
     // Write input data to scratchpad
-    result = cWriteMemory(addr, devicePage, devicePage.length);
+    result = cWriteMemory(addr, devicePage.data(), devicePage.size());
     if (result == OneWireMaster::Success)
     {
-        addr += devicePage.length;
-        result = cWriteMemory(addr, challenge, challenge.length);
+        addr += devicePage.size();
+        result = cWriteMemory(addr, challenge.data(), challenge.size());
     }
     if (result == OneWireMaster::Success)
     {
-        addr += challenge.length;
-        result = cWriteMemory(addr, authMacData, authMacData.length);
+        addr += challenge.size();
+        result = cWriteMemory(addr, authMacData.data(), authMacData.size());
     }
     // Compute MAC
     if (result == OneWireMaster::Success)
@@ -216,7 +216,7 @@
     {
         wait_ms(shaComputationDelayMs * 2);
         // Read MAC from register
-        result = readMemory(MacReadoutReg, mac, mac.length, true);
+        result = readMemory(MacReadoutReg, mac.data(), mac.size(), true);
     }
     return (result == OneWireMaster::Success ? ISha256MacCoproc::Success : ISha256MacCoproc::OperationFailure);
 }
@@ -226,16 +226,16 @@
     OneWireMaster::CmdResult result;
     int addr = Scratchpad;
     // Write input data to scratchpad
-    result = writeMemory(addr, devicePage, devicePage.length);
+    result = writeMemory(addr, devicePage.data(), devicePage.size());
     if (result == OneWireMaster::Success)
     {
-        addr += devicePage.length;
-        result = writeMemory(addr, deviceScratchpad, deviceScratchpad.length);
+        addr += devicePage.size();
+        result = writeMemory(addr, deviceScratchpad.data(), deviceScratchpad.size());
     }
     if (result == OneWireMaster::Success)
     {
-        addr += deviceScratchpad.length;
-        result = writeMemory(addr, slaveSecretData, slaveSecretData.length);
+        addr += deviceScratchpad.size();
+        result = writeMemory(addr, slaveSecretData.data(), slaveSecretData.size());
     }
     // Compute secret
     if (result == OneWireMaster::Success)
--- a/Masters/DS2465/DS2465.h	Fri Dec 02 19:21:55 2016 +0000
+++ b/Masters/DS2465/DS2465.h	Tue Dec 13 13:31:30 2016 -0800
@@ -122,7 +122,7 @@
 
         /// @param I2C_interface Configured I2C communication interface for DS2465.
         /// @param I2C_address I2C bus address of the DS2465 in mbed format.
-        DS2465(mbed::I2C & I2C_interface, uint8_t I2C_address);
+        DS2465(mbed::I2C & I2C_interface, uint8_t I2C_address = 0x30);
 
         // Const member functions should not change the settings of the DS2465 or affect the state of the 1-Wire bus.
         // Read pointer, scratchpad, MAC output register, and command register on the DS2465 are considered mutable.
--- a/Masters/DS248x/DS2482EightChannel/DS2482EightChannel.cpp	Fri Dec 02 19:21:55 2016 +0000
+++ b/Masters/DS248x/DS2482EightChannel/DS2482EightChannel.cpp	Tue Dec 13 13:31:30 2016 -0800
@@ -38,15 +38,7 @@
 
 
 //*********************************************************************
-DS2482EightChannel::DS2482EightChannel(mbed::I2C & i2c_bus, uint8_t adrs)
-:DS248x(i2c_bus, adrs)
-{
-}
-
-
-//*********************************************************************
-DS2482EightChannel::DS2482EightChannel(mbed::I2C & i2c_bus, I2CAddress adrs)
-:DS248x(i2c_bus, adrs)
+DS2482EightChannel::DS2482EightChannel(mbed::I2C & i2c_bus, uint8_t adrs) : DS248x(i2c_bus, adrs)
 {
 }
 
--- a/Masters/DS248x/DS2482EightChannel/DS2482EightChannel.h	Fri Dec 02 19:21:55 2016 +0000
+++ b/Masters/DS248x/DS2482EightChannel/DS2482EightChannel.h	Tue Dec 13 13:31:30 2016 -0800
@@ -41,10 +41,9 @@
 namespace OneWire
 {
     ///DS2482-800 I2C to 1-wire Master
-    class DS2482EightChannel: public DS248x
+    class DS2482EightChannel : public DS248x
     {
-        public:
-        
+    public:
         ///Valid slave addresses for DS2482-800
         enum I2CAddress
         {
@@ -65,15 +64,6 @@
         DS2482EightChannel(mbed::I2C & i2c_bus, uint8_t adrs);
         
         
-        /// Construct to use an existing I2C interface.
-        /// @param i2c_bus Configured I2C communication interface for DS248x.
-        /// @param adrs Enumerated I2C bus address of the DS2482_800 in mbed format.
-        DS2482EightChannel(mbed::I2C & i2c_bus, I2CAddress adrs);
-        
-        ///Destroys DS2482_800 object
-        virtual ~DS2482EightChannel(){};
-        
-        
         /// Select the 1-Wire channel on a DS2482-800.
         /// @note DS2482-800 only
         /// @param channel Channel number to select beginning at 1.
--- a/Masters/DS248x/DS2482SingleChannel/DS2482SingleChannel.h	Fri Dec 02 19:21:55 2016 +0000
+++ b/Masters/DS248x/DS2482SingleChannel/DS2482SingleChannel.h	Tue Dec 13 13:31:30 2016 -0800
@@ -41,10 +41,9 @@
 namespace OneWire
 {
     ///DS2482_100 I2C to 1-wire Master
-    class DS2482SingleChannel: public DS248x
+    class DS2482SingleChannel : public DS248x
     {
-        public:
-        
+    public:
         ///Valid slave addresses for DS2482-100
         enum I2CAddress
         {
@@ -57,15 +56,7 @@
         /// Construct to use an existing I2C interface.
         /// @param i2c_bus Configured I2C communication interface for DS248x.
         /// @param adrs I2C bus address of the DS248x in mbed format.
-        DS2482SingleChannel(mbed::I2C & i2c_bus, uint8_t adrs):DS248x(i2c_bus, adrs){};
-        
-        /// Construct to use an existing I2C interface.
-        /// @param i2c_bus Configured I2C communication interface for DS248x.
-        /// @param adrs Enumerated I2C bus address of the DS2482_100 in mbed format.
-        DS2482SingleChannel(mbed::I2C & i2c_bus, I2CAddress adrs):DS248x(i2c_bus, adrs){};
-        
-        ///Destroys DS2482_100 object
-        virtual ~DS2482SingleChannel(){};
+        DS2482SingleChannel(mbed::I2C & i2c_bus, uint8_t adrs) : DS248x(i2c_bus, adrs) { }
     };
 }
 
--- a/Masters/DS248x/DS2484/DS2484.cpp	Fri Dec 02 19:21:55 2016 +0000
+++ b/Masters/DS248x/DS2484/DS2484.cpp	Tue Dec 13 13:31:30 2016 -0800
@@ -30,21 +30,16 @@
 * ownership rights.
 **********************************************************************/
 
-
 #include "Masters/DS248x/DS2484/DS2484.h"
 
-
 using OneWire::OneWireMaster;
 using OneWire::DS2484;
 
-
 //*********************************************************************
-DS2484::DS2484(mbed::I2C & i2c_bus)
-:DS248x(i2c_bus, I2C_ADRS)
+DS2484::DS2484(mbed::I2C & i2c_bus, uint8_t adrs) : DS248x(i2c_bus, adrs)
 {
 }
 
-
 //*********************************************************************
 OneWireMaster::CmdResult DS2484::adjustOwPort(OwAdjustParam param, uint8_t val)
 {
--- a/Masters/DS248x/DS2484/DS2484.h	Fri Dec 02 19:21:55 2016 +0000
+++ b/Masters/DS248x/DS2484/DS2484.h	Tue Dec 13 13:31:30 2016 -0800
@@ -41,12 +41,9 @@
 namespace OneWire
 {
     ///DS2484 I2C to 1-wire Master
-    class DS2484: public DS248x
+    class DS2484 : public DS248x
     {
-        public:
-        
-        static const uint8_t I2C_ADRS = 0x30;
-        
+    public:        
         /// 1-Wire port adjustment parameters.
         /// @note See datasheet page 13.
         enum OwAdjustParam
@@ -63,12 +60,10 @@
         
         /// Construct to use an existing I2C interface.
         /// @param i2c_bus Configured I2C communication interface for DS248x.
-        DS2484(mbed::I2C & i2c_bus);
+        /// @param adrs I2C bus address of the DS248x in mbed format.
+        DS2484(mbed::I2C & i2c_bus, uint8_t adrs = 0x30);
         
-        ///Destroys DS2484 object
-        virtual ~DS2484(){};
-        
-        /// Adjust 1-Wire port paramaters.
+        /// Adjust 1-Wire port parameters.
         /// @note DS2484 only
         /// @param param Parameter to adjust.
         /// @param val New parameter value to set. Consult datasheet for value mappings.
--- a/Masters/DS248x/DS248x.h	Fri Dec 02 19:21:55 2016 +0000
+++ b/Masters/DS248x/DS248x.h	Tue Dec 13 13:31:30 2016 -0800
@@ -34,7 +34,6 @@
 #define OneWire_Masters_DS248x
 
 #include "Masters/OneWireMaster.h"
-#include "PinNames.h"
 
 namespace mbed { class I2C; }
 
@@ -95,11 +94,6 @@
             bool m_1WS, m_SPU, m_PDN, m_APU;
         };
         
-        /// Construct to use an existing I2C interface.
-        /// @param i2c_bus Configured I2C communication interface for DS248x.
-        /// @param adrs I2C bus address of the DS248x in mbed format.
-        DS248x(mbed::I2C & i2c_bus, uint8_t adrs);
-
         /// Performs a soft reset on the DS248x.
         /// @note This is note a 1-Wire Reset.
         OneWireMaster::CmdResult reset(void);
@@ -151,24 +145,30 @@
             OwTripletCmd = 0x78
         };
         
-        mbed::I2C & m_i2c_bus;
-        uint8_t m_adrs;
-        Config m_curConfig;
+        /// Construct to use an existing I2C interface.
+        /// @param i2c_bus Configured I2C communication interface for DS248x.
+        /// @param adrs I2C bus address of the DS248x in mbed format.
+        DS248x(mbed::I2C & i2c_bus, uint8_t adrs);
+        
+        /// @note Allow marking const since not public.
+        OneWireMaster::CmdResult sendCommand(Command cmd) const;
 
+        /// @note Allow marking const since not public.
+        OneWireMaster::CmdResult sendCommand(Command cmd, uint8_t param) const;
+    
+    private:
         /// Polls the DS248x status waiting for the 1-Wire Busy bit (1WB) to be cleared.
-        /// @param[out] pStatus Optionally retrive the status byte when 1WB cleared.
+        /// @param[out] pStatus Optionally retrieve the status byte when 1WB cleared.
         /// @returns Success or TimeoutError if poll limit reached.
         OneWireMaster::CmdResult pollBusy(uint8_t * pStatus = NULL);
 
         /// Ensure that the desired 1-Wire level is set in the configuration.
         /// @param level Desired 1-Wire level.
         OneWireMaster::CmdResult configureLevel(OWLevel level);
-
-        /// @note Allow marking const since not public.
-        OneWireMaster::CmdResult sendCommand(Command cmd) const;
-
-        /// @note Allow marking const since not public.
-        OneWireMaster::CmdResult sendCommand(Command cmd, uint8_t param) const;
+        
+        mbed::I2C & m_i2c_bus;
+        uint8_t m_adrs;
+        Config m_curConfig;
     };
 }
 
--- a/Masters/OneWireMaster.cpp	Fri Dec 02 19:21:55 2016 +0000
+++ b/Masters/OneWireMaster.cpp	Tue Dec 13 13:31:30 2016 -0800
@@ -31,9 +31,6 @@
 **********************************************************************/
 
 #include "Masters/OneWireMaster.h"
-#include "Utilities/crc.h"
-
-using namespace OneWire::crc;
 
 namespace OneWire
 {
--- a/Masters/TARGET_Maxim/TARGET_MAX32600/OwGpio/OwGpio.cpp	Fri Dec 02 19:21:55 2016 +0000
+++ b/Masters/TARGET_Maxim/TARGET_MAX32600/OwGpio/OwGpio.cpp	Tue Dec 13 13:31:30 2016 -0800
@@ -223,4 +223,3 @@
 }
 
 #endif /* TARGET_MAX32600 */
-
--- a/Masters/TARGET_Maxim/TARGET_MAX32600/OwGpio/OwGpio.h	Fri Dec 02 19:21:55 2016 +0000
+++ b/Masters/TARGET_Maxim/TARGET_MAX32600/OwGpio/OwGpio.h	Tue Dec 13 13:31:30 2016 -0800
@@ -74,4 +74,3 @@
 #endif /* TARGET_MAX32600 */
 
 #endif
-
--- a/Masters/TARGET_Maxim/TARGET_MAX32600/OwGpio/owlink.h	Fri Dec 02 19:21:55 2016 +0000
+++ b/Masters/TARGET_Maxim/TARGET_MAX32600/OwGpio/owlink.h	Tue Dec 13 13:31:30 2016 -0800
@@ -73,4 +73,3 @@
 #endif /* TARGET_MAX32600 */
 
 #endif /* OWLINK_H */
-
--- a/Masters/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_ARM_STD/owlink.s	Fri Dec 02 19:21:55 2016 +0000
+++ b/Masters/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_ARM_STD/owlink.s	Tue Dec 13 13:31:30 2016 -0800
@@ -197,4 +197,3 @@
   bx R14
   
   END
-
--- a/Masters/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_GCC_ARM/owlink.S	Fri Dec 02 19:21:55 2016 +0000
+++ b/Masters/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_GCC_ARM/owlink.S	Tue Dec 13 13:31:30 2016 -0800
@@ -197,4 +197,4 @@
   pop {R4-R8, R14}
   bx R14
   .end
-  
+  
\ No newline at end of file
--- a/Masters/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_IAR/owlink.s	Fri Dec 02 19:21:55 2016 +0000
+++ b/Masters/TARGET_Maxim/TARGET_MAX32600/TOOLCHAIN_IAR/owlink.s	Tue Dec 13 13:31:30 2016 -0800
@@ -195,4 +195,3 @@
   pop {R4-R8, R14}
   bx R14
   END
-
--- a/RomId/RomCommands.cpp	Fri Dec 02 19:21:55 2016 +0000
+++ b/RomId/RomCommands.cpp	Tue Dec 13 13:31:30 2016 -0800
@@ -54,13 +54,13 @@
             last_discrepancy = 0;
             last_device_flag = false;
             last_family_discrepancy = 0;
-            romId.reset();
+            romId = RomId();
         }
 
         void SearchState::findFamily(uint8_t familyCode)
         {
             reset();
-            romId.setFamilyCode(familyCode);
+            romId.familyCode() = familyCode;
             last_discrepancy = 64;
         }
 
@@ -130,13 +130,13 @@
             // read the ROM
             if (result == OneWireMaster::Success)
             {
-                result = master.OWReadBlock(readId, RomId::byteLen);
+                result = master.OWReadBlock(readId.buffer.data(), readId.buffer.size());
             }
 
             // verify CRC8
             if (result == OneWireMaster::Success)
             {
-                if (readId.crc8Valid())
+                if (readId.valid())
                 {
                     romId = readId;
                 }
@@ -148,7 +148,7 @@
 
             return result;
         }
-          
+        
         OneWireMaster::CmdResult OWSkipRom(OneWireMaster & master)
         {
             OneWireMaster::CmdResult result;
@@ -161,26 +161,26 @@
 
             return result;
         }
-          
+        
         OneWireMaster::CmdResult OWMatchRom(OneWireMaster & master, const RomId & romId)
         {
             OneWireMaster::CmdResult result;
 
-            uint8_t buf[1 + RomId::byteLen];
+            uint8_t buf[1 + RomId::Buffer::csize];
 
             // use MatchROM
             result = master.OWReset();
             if (result == OneWireMaster::Success)
             {
                 buf[0] = MatchRomCmd;
-                std::memcpy(&buf[1], romId, RomId::byteLen);
+                std::memcpy(&buf[1], romId.buffer.data(), romId.buffer.size());
                 // send command and rom
-                result = master.OWWriteBlock(buf, 1 + RomId::byteLen);
+                result = master.OWWriteBlock(buf, 1 + romId.buffer.size());
             }
 
             return result;
         }
-          
+        
         OneWireMaster::CmdResult OWOverdriveSkipRom(OneWireMaster & master)
         {
             OneWireMaster::CmdResult result = master.OWSetSpeed(OneWireMaster::StandardSpeed);
@@ -218,12 +218,12 @@
                 {
                     master.OWSetSpeed(OneWireMaster::OverdriveSpeed);
                     // send ROM
-                    result = master.OWWriteBlock(romId, RomId::byteLen);
+                    result = master.OWWriteBlock(romId.buffer.data(), romId.buffer.size());
                 }
             }
             return result;
         }
-           
+        
         OneWireMaster::CmdResult OWResume(OneWireMaster & master)
         {
             OneWireMaster::CmdResult result;
@@ -276,7 +276,7 @@
                     // on a previous next then pick the same as last time
                     if (id_bit_number < searchState.last_discrepancy)
                     {
-                        if ((searchState.romId[rom_byte_number] & rom_byte_mask) > 0)
+                        if ((searchState.romId.buffer[rom_byte_number] & rom_byte_mask) > 0)
                         {
                             search_direction = OneWireMaster::WriteOne;
                         }
@@ -327,11 +327,11 @@
                         // with mask rom_byte_mask
                         if (search_direction == OneWireMaster::WriteOne)
                         {
-                            searchState.romId[rom_byte_number] |= rom_byte_mask;
+                            searchState.romId.buffer[rom_byte_number] |= rom_byte_mask;
                         }
                         else
                         {
-                            searchState.romId[rom_byte_number] &= (uint8_t)~rom_byte_mask;
+                            searchState.romId.buffer[rom_byte_number] &= (uint8_t)~rom_byte_mask;
                         }
 
                         // increment the byte counter id_bit_number
@@ -342,15 +342,15 @@
                         // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
                         if (rom_byte_mask == 0)
                         {
-                            crc8 = calculateCrc8(crc8, searchState.romId[rom_byte_number]);  // accumulate the CRC
+                            crc8 = calculateCrc8(crc8, searchState.romId.buffer[rom_byte_number]);  // accumulate the CRC
                             rom_byte_number++;
                             rom_byte_mask = 1;
                         }
                     }
-                } while (rom_byte_number < RomId::byteLen);  // loop until through all ROM bytes 0-7
+                } while (rom_byte_number < searchState.romId.buffer.size());  // loop until through all ROM bytes 0-7
 
                 // if the search was successful then
-                if (!((id_bit_number <= (RomId::byteLen * 8)) || (crc8 != 0)))
+                if (!((id_bit_number <= (searchState.romId.buffer.size() * 8)) || (crc8 != 0)))
                 {
                     // search successful so set m_last_discrepancy,m_last_device_flag,search_result
                     searchState.last_discrepancy = last_zero;
--- a/RomId/RomId.h	Fri Dec 02 19:21:55 2016 +0000
+++ b/RomId/RomId.h	Tue Dec 13 13:31:30 2016 -0800
@@ -38,108 +38,37 @@
 
 namespace OneWire
 {
-  /// Standard container for a 1-Wire ROM ID.
-  class RomId
-  {
-  public:
-      /// Length of the buffer in bytes.
-      static const size_t byteLen = 8;
-      
-      /// Built-in array representation.
-      typedef array<uint8_t, byteLen>::Buffer ByteBuffer;
+    /// Standard container for a 1-Wire ROM ID.
+    struct RomId
+    {
+        typedef array<uint8_t, 8> Buffer;
+    
+        /// Direct access to the buffer.
+        Buffer buffer;
+        /// @}
 
-  private:
-      static const size_t familyCodeIdx = 0;
-      static const size_t crc8Idx = 7;
-      
-      /// Default starting value is all bytes 0x00.
-      static const uint8_t defaultByteVal = 0x00;
-
-      array<uint8_t, byteLen> m_romId;
-
-  public:
-      RomId() { reset(); }
-      RomId(const RomId & romId) : m_romId(romId.m_romId) { }
-      RomId(const ByteBuffer & romIdBytes) : m_romId(romIdBytes) { }
+        /// @{
+        /// Access the Family Code byte.
+        uint8_t & familyCode() { return buffer.front(); }
+        const uint8_t & familyCode() const { return buffer.front(); }
+        /// @}
 
-      const RomId & operator=(const RomId & rhs)
-      {
-          this->m_romId = rhs.m_romId;
-          return rhs;
-      }
-      
-      bool operator==(const RomId & rhs) const
-      {
-          return (this->m_romId == rhs.m_romId);
-      }
-      
-      bool operator!=(const RomId & rhs) const
-      {
-          return !operator==(rhs);
-      }
-      
-      /// Conversion to array reference.
-      operator ByteBuffer &()
-      {
-          return m_romId;
-      }
-      
-      /// Conversion to const array reference.
-      operator const ByteBuffer &() const
-      {
-          return m_romId;
-      }
-
-      /// Reset to the default starting value.
-      void reset()
-      {
-          std::memset(m_romId, defaultByteVal, byteLen);
-      }
+        /// @{
+        /// Access the CRC8 byte.
+        uint8_t & crc8() { return buffer.back(); }
+        const uint8_t & crc8() const { return buffer.back(); }
+        /// @}
 
-      /// Read the Family Code byte.
-      uint8_t familyCode() const
-      {
-          return m_romId[familyCodeIdx];
-      }
-      
-      /// Set the family code byte.
-      void setFamilyCode(uint8_t familyCode)
-      {
-          m_romId[familyCodeIdx] = familyCode;
-      }
-
-      /// Read the CRC8 byte.
-      uint8_t crc8() const
-      {
-          return m_romId[crc8Idx];
-      }
-      
-      /// Set the CRC8 byte.
-      void setCrc8(uint8_t crc8)
-      {
-          m_romId[crc8Idx] = crc8;
-      }
-      
-      /// Check if the CRC8 is valid for the ROM ID.
-      /// @returns True if the CRC8 is valid.
-      bool crc8Valid() const
-      {
-          return (crc::calculateCrc8(m_romId, (byteLen - 1), 0x00) == crc8());
-      }
-      
-      /// Calculate and set the CRC8 for the ROM ID.
-      void setValidCrc8()
-      {
-          setCrc8(crc::calculateCrc8(m_romId, (byteLen - 1), 0x00));
-      }
-
-      /// Check if the ROM ID is valid (Family Code and CRC8 are both valid).
-      /// @returns True if the ROM ID is valid.
-      bool valid() const
-      {
-          return (crc8Valid() && (familyCode() != defaultByteVal));
-      }
-  };
+        /// Check if the ROM ID is valid (Family Code and CRC8 are both valid).
+        /// @returns True if the ROM ID is valid.
+        bool valid() const
+        {
+            return crc::calculateCrc8(buffer.data(), buffer.size() - 1, 0x00) == crc8();
+        }
+        
+        bool operator==(const RomId & rhs) const { return (this->buffer == rhs.buffer); }
+        bool operator!=(const RomId & rhs) const { return !operator==(rhs); }
+    };
 }
 
 #endif
--- a/Slaves/Authenticators/DS28E15_22_25/DS28E15.h	Fri Dec 02 19:21:55 2016 +0000
+++ b/Slaves/Authenticators/DS28E15_22_25/DS28E15.h	Tue Dec 13 13:31:30 2016 -0800
@@ -36,15 +36,75 @@
 #include "DS28E15_22_25.h"
 
 namespace OneWire
-{
+{    
     /// Interface to the DS28E15 and DS28EL15 (low power) authenticators.
     class DS28E15 : public DS28E15_22_25
     {
-    public:    
+    public:            
+        // DS28E15_22_25 traits
+        static const unsigned int memoryPages = 2;
+        static const unsigned int protectionBlocks = 4;
+    
         /// @param owMaster 1-Wire Master to use for communication with DS28E15.
         /// @param lowVoltage Enable low voltage timing.
         DS28E15(RandomAccessRomIterator & selector, bool lowVoltage = false)
-            : DS28E15_22_25(selector, lowVoltage, DS28E15_Family) { }
+            : DS28E15_22_25(selector, lowVoltage) { }
+            
+        /// Perform Write Scratchpad operation on the device.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param[in] data Data to write to the scratchpad.
+        CmdResult writeScratchpad(const Scratchpad & data) const;
+
+        /// Perform a Read Scratchpad operation on the device.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param[out] data Buffer to read data from the scratchpad into.
+        CmdResult readScratchpad(Scratchpad & data) const;
+        
+        /// Read the status of a memory protection block using the Read Status command.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param blockNum Block number to to read status of.
+        /// @param[out] protection Receives protection status read from device.
+        CmdResult readBlockProtection(unsigned int blockNum, BlockProtection & protection) const;
+
+        /// Read the personality bytes using the Read Status command.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param[out] personality Receives personality read from device.
+        CmdResult readPersonality(Personality & personality) const;
+        
+        /// Write memory segment with authentication using the Authenticated Write Memory command.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param MacCoproc Coprocessor to use for Write MAC computation.
+        /// @param pageNum Page number for write operation.
+        /// @param segmentNum Segment number within page for write operation.
+        /// @param[in] newData New data to write to the segment.
+        /// @param[in] oldData Existing data contained in the segment.
+        /// @param continuing True to continue writing with the next sequential segment.
+        ///                   False to begin a new command.
+        CmdResult writeAuthSegment(const ISha256MacCoproc & MacCoproc,
+                                   unsigned int pageNum,
+                                   unsigned int segmentNum,
+                                   const Segment & newData,
+                                   const Segment & oldData,
+                                   bool continuing = false);
+
+        /// Write memory segment with authentication using the Authenticated Write Memory command.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param pageNum Page number for write operation.
+        /// @param segmentNum Segment number within page for write operation.
+        /// @param[in] newData New data to write to the segment.
+        /// @param[in] mac Write MAC computed for this operation.
+        /// @param continuing True to continue writing with the next sequential segment.
+        ///                   False to begin a new command.
+        CmdResult writeAuthSegmentMac(unsigned int pageNum,
+                                      unsigned int segmentNum,
+                                      const Segment & newData,
+                                      const Mac & mac,
+                                      bool continuing = false);
+        
+        /// Read the status of all memory protection blocks using the Read Status command.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param[out] protection Receives protection statuses read from device.    
+        CmdResult readAllBlockProtection(array<BlockProtection, protectionBlocks> & protection) const;
     };
 }
 
--- a/Slaves/Authenticators/DS28E15_22_25/DS28E15_22_25.cpp	Fri Dec 02 19:21:55 2016 +0000
+++ b/Slaves/Authenticators/DS28E15_22_25/DS28E15_22_25.cpp	Tue Dec 13 13:31:30 2016 -0800
@@ -31,8 +31,12 @@
 **********************************************************************/
 
 #include "DS28E15_22_25.h"
+#include "DS28E15.h"
+#include "DS28E22.h"
+#include "DS28E25.h"
 #include "Masters/OneWireMaster.h"
 #include "Utilities/crc.h"
+#include "Utilities/type_traits.h"
 #include "wait_api.h"
 
 using namespace OneWire;
@@ -53,41 +57,28 @@
     AuthWriteBlockProtection = 0xCC,
 };
 
-/// Number for memory pages for each device.
-enum MemoryPages
-{
-    DS28E25_Pages = 16,
-    DS28E22_Pages = 8,
-    DS28E15_Pages = 2
-};
-
-/// Number of protection blocks for each device.
-enum ProtectionBlocks
-{
-    DS28E25_Blocks = 8,
-    DS28E22_Blocks = 4,
-    DS28E15_Blocks = 4
-};
-
-DS28E15_22_25::Segment DS28E15_22_25::Page::toSegment(unsigned int segmentNum) const
+DS28E15_22_25::Segment DS28E15_22_25::segmentFromPage(unsigned int segmentNum, const Page & page)
 {
     if (segmentNum > (segmentsPerPage - 1))
     {
         segmentNum = (segmentsPerPage - 1);
     }
-    return Segment(*reinterpret_cast<const Segment::Buffer *>(&m_data[segmentNum * sizeof(Segment::Buffer)]));
+    Segment segment;
+    Page::const_iterator copyBegin = page.begin() + (segmentNum * Segment::size());
+    std::copy(copyBegin, copyBegin + Segment::size(), segment.begin());
+    return segment;
 }
 
-void DS28E15_22_25::Page::fromSegment(unsigned int segmentNum, const Segment & segment)
+void DS28E15_22_25::segmentToPage(unsigned int segmentNum, const Segment & segment, Page & page)
 {
     if (segmentNum > (segmentsPerPage - 1))
     {
         segmentNum = (segmentsPerPage - 1);
     }
-    std::memcpy(&m_data[segmentNum * sizeof(Segment::Buffer)], &static_cast<const Segment::Buffer &>(segment), Segment::length);
+    std::copy(segment.begin(), segment.end(), page.begin() + (segmentNum * segment.size()));
 }
 
-DS28E15_22_25::BlockProtection::BlockProtection(bool readProtection, bool writeProtection, bool eepromEmulation, bool authProtection, uint8_t blockNum)
+DS28E15_22_25::BlockProtection::BlockProtection(bool readProtection, bool writeProtection, bool eepromEmulation, bool authProtection, unsigned int blockNum)
 {
     setReadProtection(readProtection);
     setWriteProtection(writeProtection);
@@ -96,7 +87,7 @@
     setBlockNum(blockNum);
 }
 
-void DS28E15_22_25::BlockProtection::setBlockNum(uint8_t blockNum)
+void DS28E15_22_25::BlockProtection::setBlockNum(unsigned int blockNum)
 {
     m_status &= ~blockNumMask;
     m_status |= (blockNum & blockNumMask);
@@ -155,10 +146,10 @@
     }
 }
 
-DS28E15_22_25::DS28E15_22_25(RandomAccessRomIterator & selector, bool lowVoltage, FamilyCode variant)
-    : OneWireSlave(selector), m_lowVoltage(lowVoltage), m_variant(variant)
+DS28E15_22_25::DS28E15_22_25(RandomAccessRomIterator & selector, bool lowVoltage)
+    : OneWireSlave(selector), m_manId(), m_lowVoltage(lowVoltage)
 {
-    std::memset(m_manId, 0x00, m_manId.length);
+
 }
 
 OneWireSlave::CmdResult DS28E15_22_25::writeAuthBlockProtection(const ISha256MacCoproc & MacCoproc, const BlockProtection & newProtection, const BlockProtection & oldProtection)
@@ -191,7 +182,7 @@
     master().OWSetLevel(OneWireMaster::NormalLevel);
 
     // check CRC16
-    if (calculateCrc16(buf, 0, cnt) != 0xB001)
+    if (calculateCrc16(buf, cnt) != 0xB001)
     {
         return CrcError;
     }
@@ -205,14 +196,14 @@
     cnt = 0;
 
     // send the MAC
-    master().OWWriteBlock(mac, mac.length);
+    master().OWWriteBlock(mac.data(), mac.size());
 
     // Read CRC and CS byte
     master().OWReadBlock(&buf[cnt], 3);
     cnt += 3;
 
     // check CRC16
-    if (calculateCrc16(buf, 0, (cnt - 1), calculateCrc16(mac, 0, mac.length)) != 0xB001)
+    if (calculateCrc16(buf, cnt - 1, calculateCrc16(mac.data(), mac.size())) != 0xB001)
     {
         return CrcError;
     }
@@ -266,7 +257,7 @@
     cnt += 2;
 
     // check CRC16
-    if (calculateCrc16(buf, 0, cnt) != 0xB001)
+    if (calculateCrc16(buf, cnt) != 0xB001)
     {
         return CrcError;
     }
@@ -291,12 +282,13 @@
     return OperationFailure;
 }
 
-OneWireSlave::CmdResult DS28E15_22_25::readBlockProtection(unsigned int blockNum, BlockProtection & protection)
+template <class T>
+OneWireSlave::CmdResult DS28E15_22_25::doReadBlockProtection(unsigned int blockNum, BlockProtection & protection) const
 {
     uint8_t buf;
     CmdResult result;
     
-    result = readStatus(false, false, blockNum, &buf);
+    result = readStatus<T>(false, false, blockNum, &buf);
     if (result == Success)
     {
         protection.setStatusByte(buf);
@@ -304,11 +296,19 @@
     return result;
 }
 
-OneWireSlave::CmdResult DS28E15_22_25::readPersonality(Personality & personality) const
+template <class T>
+OneWireSlave::CmdResult DS28E15_22_25::doReadPersonality(Personality & personality) const
 {
-    return readStatus(true, false, 0, personality.bytes);
+    Personality::Buffer buffer;
+    CmdResult result = readStatus<T>(true, false, 0, buffer.data());
+    if (result == Success)
+    {
+        personality = Personality(buffer);
+    }
+    return result;
 }
 
+template <class T>
 OneWireSlave::CmdResult DS28E15_22_25::readStatus(bool personality, bool allpages, unsigned int blockNum, uint8_t * rdbuf) const
 {
     const size_t crcLen = 4, ds28e22_25_pagesPerBlock = 2;
@@ -334,7 +334,7 @@
     {
         // Convert to page number for DS28E22 and DS28E25
         buf[cnt] = blockNum;
-        if ((m_variant == DS28E25_Family) || (m_variant == DS28E22_Family))
+        if (is_same<T, DS28E22>::value || is_same<T, DS28E25>::value)
         {
             buf[cnt] *= ds28e22_25_pagesPerBlock;
         }
@@ -356,13 +356,13 @@
     {
         rdnum = 1;
     }
-    else if ((m_variant == DS28E22_Family) || (m_variant == DS28E25_Family))
+    else if (is_same<T, DS28E22>::value || is_same<T, DS28E25>::value)
     {
-        rdnum = DS28E25_Pages; // Need to read extra data on DS28E22 to get CRC16.
+        rdnum = DS28E25::memoryPages; // Need to read extra data on DS28E22 to get CRC16.
     }
     else // DS28E15
     {
-        rdnum = DS28E15_Blocks;
+        rdnum = DS28E15::protectionBlocks;
     }
     rdnum += crcLen; // Add in CRC length
 
@@ -371,7 +371,7 @@
     cnt += rdnum;
 
     // check the first CRC16
-    if (calculateCrc16(buf, 0, offset) != 0xB001)
+    if (calculateCrc16(buf, offset) != 0xB001)
     {
         return CrcError;
     }
@@ -379,7 +379,7 @@
     if (personality || allpages)
     {
         // check the second CRC16
-        if (calculateCrc16(buf, offset, (cnt - offset)) != 0xB001)
+        if (calculateCrc16(buf + offset, cnt - offset) != 0xB001)
         {
             return CrcError;
         }
@@ -387,11 +387,11 @@
 
     // copy the data to the read buffer
     rdnum -= crcLen;
-    if (allpages && ((m_variant == DS28E25_Family) || (m_variant == DS28E22_Family)))
+    if (allpages && (is_same<T, DS28E22>::value || is_same<T, DS28E25>::value))
     {
-        if (m_variant == DS28E22_Family)
+        if (is_same<T, DS28E22>::value)
         {
-            rdnum -= (DS28E25_Pages - DS28E22_Pages);
+            rdnum -= (DS28E25::memoryPages - DS28E22::memoryPages);
         }
 
         for (size_t i = 0; i < (rdnum / ds28e22_25_pagesPerBlock); i++)
@@ -413,7 +413,7 @@
     ISha256MacCoproc::AuthMacData authMacData;
 
     // insert ROM number or FF
-    std::memcpy(authMacData, romId, RomId::byteLen);
+    std::memcpy(authMacData.data(), romId.buffer.data(), romId.buffer.size());
 
     authMacData[10] = pageNum;
 
@@ -428,7 +428,7 @@
 ISha256MacCoproc::CmdResult DS28E15_22_25::computeAuthMacAnon(const ISha256MacCoproc & MacCoproc, const Page & pageData, unsigned int pageNum, const Scratchpad & challenge, const ManId & manId, Mac & mac)
 {
     RomId romId;
-    std::memset(romId, 0xFF, RomId::byteLen);
+    romId.buffer.fill(0xFF);
     return computeAuthMac(MacCoproc, pageData, pageNum, challenge, romId, manId, mac);
 }
 
@@ -461,7 +461,7 @@
     master().OWSetLevel(OneWireMaster::NormalLevel);
 
     // check CRC16
-    if (calculateCrc16(buf, 0, cnt) != 0xB001)
+    if (calculateCrc16(buf, cnt) != 0xB001)
     {
         return CrcError;
     }
@@ -474,16 +474,16 @@
     }
 
     // read the MAC and CRC
-    master().OWReadBlock(&buf[0], (Mac::length + 2));
+    master().OWReadBlock(&buf[0], (Mac::size() + 2));
 
     // check CRC16
-    if (calculateCrc16(buf, 0, (Mac::length + 2)) != 0xB001)
+    if (calculateCrc16(buf, Mac::size() + 2) != 0xB001)
     {
         return CrcError;
     }
 
     // copy MAC to return buffer
-    std::memcpy(mac, buf, Mac::length);
+    std::memcpy(mac.data(), buf, mac.size());
 
     return Success;
 }
@@ -509,7 +509,7 @@
     cnt += 2;
 
     // check CRC16
-    if (calculateCrc16(buf, 0, cnt) != 0xB001)
+    if (calculateCrc16(buf, cnt) != 0xB001)
     {
         return CrcError;
     }
@@ -534,7 +534,8 @@
     return OperationFailure;
 }
 
-OneWireSlave::CmdResult DS28E15_22_25::writeScratchpad(const Scratchpad & data) const
+template <class T>
+OneWireSlave::CmdResult DS28E15_22_25::doWriteScratchpad(const Scratchpad & data) const
 {
     uint8_t buf[256];
     int cnt = 0, offset;
@@ -545,7 +546,7 @@
     }
 
     buf[cnt++] = ReadWriteScratchpad;
-    if ((m_variant == DS28E25_Family) || (m_variant == DS28E22_Family))
+    if (is_same<T, DS28E22>::value || is_same<T, DS28E25>::value)
     {
         buf[cnt++] = 0x20;
     }
@@ -564,24 +565,24 @@
     offset = cnt;
 
     // add the data
-    std::memcpy(&buf[cnt], data, data.length);
-    cnt += data.length;
+    std::memcpy(&buf[cnt], data.data(), data.size());
+    cnt += data.size();
 
     // Send the data
-    master().OWWriteBlock(data, data.length);
+    master().OWWriteBlock(data.data(), data.size());
 
     // Read CRC
     master().OWReadBlock(&buf[cnt], 2);
     cnt += 2;
 
     // check first CRC16
-    if (calculateCrc16(buf, 0, offset) != 0xB001)
+    if (calculateCrc16(buf, offset) != 0xB001)
     {
         return CrcError;
     }
 
     // check the second CRC16
-    if (calculateCrc16(buf, offset, (cnt - offset)) != 0xB001)
+    if (calculateCrc16(buf + offset, cnt - offset) != 0xB001)
     {
         return CrcError;
     }
@@ -589,7 +590,8 @@
     return Success;
 }
 
-OneWireSlave::CmdResult DS28E15_22_25::readScratchpad(Scratchpad & data) const
+template <class T>
+OneWireSlave::CmdResult DS28E15_22_25::doReadScratchpad(Scratchpad & data) const
 {
     uint8_t buf[256];
     int cnt = 0, offset;
@@ -600,7 +602,7 @@
     }
 
     buf[cnt++] = ReadWriteScratchpad;
-    if ((m_variant == DS28E25_Family) || (m_variant == DS28E22_Family))
+    if (is_same<T, DS28E22>::value || is_same<T, DS28E25>::value)
     {
         buf[cnt++] = 0x2F;
     }
@@ -619,27 +621,27 @@
     offset = cnt;
 
     // Receive the data
-    master().OWReadBlock(&buf[cnt], data.length);
-    cnt += data.length;
+    master().OWReadBlock(&buf[cnt], data.size());
+    cnt += data.size();
 
     // Read CRC
     master().OWReadBlock(&buf[cnt], 2);
     cnt += 2;
 
     // check first CRC16
-    if (calculateCrc16(buf, 0, offset) != 0xB001)
+    if (calculateCrc16(buf, offset) != 0xB001)
     {
         return CrcError;
     }
 
     // check the second CRC16
-    if (calculateCrc16(buf, offset, (cnt - offset)) != 0xB001)
+    if (calculateCrc16(buf + offset, cnt - offset) != 0xB001)
     {
         return CrcError;
     }
 
     // Copy to output
-    std::memcpy(data, &buf[offset], data.length);
+    std::memcpy(data.data(), &buf[offset], data.size());
 
     return Success;
 }
@@ -665,7 +667,7 @@
     cnt += 2;
 
     // check CRC16
-    if (calculateCrc16(buf, 0, cnt) != 0xB001)
+    if (calculateCrc16(buf, cnt) != 0xB001)
     {
         return CrcError;
     }
@@ -693,10 +695,8 @@
 OneWireSlave::CmdResult DS28E15_22_25::readPage(unsigned int page, Page & rdbuf, bool continuing) const
 {
     uint8_t buf[256];
-    int cnt, offset;
-
-    cnt = 0;
-    offset = 0;
+    int cnt = 0;
+    int offset = 0;
 
     // check if not continuing a previous block write
     if (!continuing)
@@ -720,31 +720,32 @@
     }
 
     // read data and CRC16
-    master().OWReadBlock(&buf[cnt], (rdbuf.length + 2));
+    master().OWReadBlock(&buf[cnt], (rdbuf.size() + 2));
     cnt += 34;
 
     // check the first CRC16
     if (!continuing)
     {
-        if (calculateCrc16(buf, 0, offset) != 0xB001)
+        if (calculateCrc16(buf, offset) != 0xB001)
         {
             return CrcError;
         }
     }
 
     // check the second CRC16
-    if (calculateCrc16(buf, offset, (cnt - offset)) != 0xB001)
+    if (calculateCrc16(buf + offset, cnt - offset) != 0xB001)
     {
         return CrcError;
     }
 
     // copy the data to the read buffer
-    std::memcpy(rdbuf, &buf[offset], rdbuf.length);
+    std::memcpy(rdbuf.data(), &buf[offset], rdbuf.size());
 
     return Success;
 }
 
-OneWireSlave::CmdResult DS28E15_22_25::writeAuthSegmentMac(unsigned int pageNum, unsigned int segmentNum, const Segment & newData, const Mac & mac, bool continuing)
+template <class T>
+OneWireSlave::CmdResult DS28E15_22_25::doWriteAuthSegmentMac(unsigned int pageNum, unsigned int segmentNum, const Segment & newData, const Mac & mac, bool continuing)
 {
     uint8_t buf[256], cs;
     int cnt, offset;
@@ -774,13 +775,13 @@
     }
 
     // add the data
-    for (size_t i = 0; i < newData.length; i++)
+    for (size_t i = 0; i < newData.size(); i++)
     {
         buf[cnt++] = newData[i];
     }
 
     // Send data
-    master().OWWriteBlock(newData, newData.length);
+    master().OWWriteBlock(newData.data(), newData.size());
 
     // read first CRC byte
     master().OWReadByte(buf[cnt++]);
@@ -797,7 +798,7 @@
     // check the first CRC16
     if (!continuing)
     {
-        if (calculateCrc16(buf, 0, offset) != 0xB001)
+        if (calculateCrc16(buf, offset) != 0xB001)
         {
             return CrcError;
         }
@@ -807,7 +808,7 @@
     uint16_t CRC16 = 0;
 
     // DS28E25/DS28E22, crc gets calculagted with CS byte 
-    if ((m_variant == DS28E25_Family) || (m_variant == DS28E22_Family))
+    if (is_same<T, DS28E22>::value || is_same<T, DS28E25>::value)
     {
         if (continuing)
         {
@@ -815,7 +816,7 @@
         }
     }
 
-    CRC16 = calculateCrc16(buf, offset, (cnt - offset), CRC16);
+    CRC16 = calculateCrc16(buf + offset, cnt - offset, CRC16);
 
     if (CRC16 != 0xB001)
     {
@@ -823,17 +824,17 @@
     }
 
     // transmit MAC as a block
-    master().OWWriteBlock(mac, mac.length);
+    master().OWWriteBlock(mac.data(), mac.size());
 
     // calculate CRC on MAC
-    CRC16 = calculateCrc16(mac, 0, mac.length);
+    CRC16 = calculateCrc16(mac.data(), mac.size());
 
     // append read of CRC16 and CS byte
     master().OWReadBlock(&buf[0], 3);
     cnt = 3;
 
     // ckeck CRC16
-    CRC16 = calculateCrc16(buf, 0, (cnt - 1), CRC16);
+    CRC16 = calculateCrc16(buf, cnt - 1, CRC16);
 
     if (CRC16 != 0xB001)
     {
@@ -871,7 +872,7 @@
     ISha256MacCoproc::WriteMacData MT;
 
     // insert ROM number
-    std::memcpy(&MT[0], romId, RomId::byteLen);
+    std::memcpy(&MT[0], romId.buffer.data(), romId.buffer.size());
 
     MT[11] = segmentNum;
     MT[10] = pageNum;
@@ -879,10 +880,10 @@
     MT[8] = manId[1];
 
     // insert old data
-    std::memcpy(&MT[12], oldData, Segment::length);
+    std::memcpy(&MT[12], oldData.data(), oldData.size());
 
     // insert new data
-    std::memcpy(&MT[16], newData, Segment::length);
+    std::memcpy(&MT[16], newData.data(), newData.size());
 
     return MacCoproc.computeWriteMac(MT, mac);
 }
@@ -892,7 +893,7 @@
     ISha256MacCoproc::WriteMacData MT;
 
     // insert ROM number
-    std::memcpy(MT, romId, RomId::byteLen);
+    std::memcpy(MT.data(), romId.buffer.data(), romId.buffer.size());
 
     // instert block and page
     MT[11] = 0;
@@ -916,7 +917,8 @@
     return MacCoproc.computeWriteMac(MT, mac);
 }
 
-OneWireSlave::CmdResult DS28E15_22_25::writeAuthSegment(const ISha256MacCoproc & MacCoproc, unsigned int pageNum, unsigned int segmentNum, const Segment & newData, const Segment & oldData, bool continuing)
+template <class T>
+OneWireSlave::CmdResult DS28E15_22_25::doWriteAuthSegment(const ISha256MacCoproc & MacCoproc, unsigned int pageNum, unsigned int segmentNum, const Segment & newData, const Segment & oldData, bool continuing)
 {
     uint8_t buf[256], cs;
     int cnt, offset;
@@ -946,13 +948,13 @@
     }
 
     // add the data
-    for (size_t i = 0; i < newData.length; i++)
+    for (size_t i = 0; i < newData.size(); i++)
     {
         buf[cnt++] = newData[i];
     }
 
     // Send data
-    master().OWWriteBlock(newData, newData.length);
+    master().OWWriteBlock(newData.data(), newData.size());
 
     // read first CRC byte
     master().OWReadByte(buf[cnt++]);
@@ -969,7 +971,7 @@
     // check the first CRC16
     if (!continuing)
     {
-        if (calculateCrc16(buf, 0, offset) != 0xB001)
+        if (calculateCrc16(buf, offset) != 0xB001)
         {
             return CrcError;
         }
@@ -978,14 +980,14 @@
     // check the second CRC16
     uint16_t CRC16 = 0;
 
-    // DS28E25/DS28E22, crc gets calculagted with CS byte
-    if ((m_variant == DS28E25_Family) || (m_variant == DS28E22_Family))
+    // DS28E25/DS28E22, crc gets calculated with CS byte
+    if (is_same<T, DS28E22>::value || is_same<T, DS28E25>::value)
     {
         if (continuing)
             CRC16 = calculateCrc16(CRC16, 0xAA);
     }
 
-    CRC16 = calculateCrc16(buf, offset, (cnt - offset), CRC16);
+    CRC16 = calculateCrc16(buf + offset, cnt - offset, CRC16);
 
     if (CRC16 != 0xB001)
     {
@@ -1002,17 +1004,17 @@
     }
 
     // transmit MAC as a block
-    master().OWWriteBlock(mac, mac.length);
+    master().OWWriteBlock(mac.data(), mac.size());
 
     // calculate CRC on MAC
-    CRC16 = calculateCrc16(mac, 0, mac.length);
+    CRC16 = calculateCrc16(mac.data(), mac.size());
 
     // append read of CRC16 and CS byte
     master().OWReadBlock(&buf[0], 3);
     cnt = 3;
 
     // ckeck CRC16
-    CRC16 = calculateCrc16(buf, 0, (cnt - 1), CRC16);
+    CRC16 = calculateCrc16(buf, cnt - 1, CRC16);
 
     if (CRC16 != 0xB001)
     {
@@ -1075,7 +1077,7 @@
     // Receive data
     if (result == OneWireMaster::Success)
     {
-        result = master().OWReadBlock(data, data.length);
+        result = master().OWReadBlock(data.data(), data.size());
     }
 
     return (result == OneWireMaster::Success ? OneWireSlave::Success : OneWireSlave::CommunicationError);
@@ -1112,13 +1114,13 @@
     }
 
     // add the data
-    for (size_t i = 0; i < data.length; i++)
+    for (size_t i = 0; i < data.size(); i++)
     {
         buf[cnt++] = data[i];
     }
 
     // Send data
-    master().OWWriteBlock(data, data.length);
+    master().OWWriteBlock(data.data(), data.size());
 
     // Read CRC
     master().OWReadBlock(&buf[cnt], 2);
@@ -1127,14 +1129,14 @@
     // check the first CRC16
     if (!continuing)
     {
-        if (calculateCrc16(buf, 0, offset) != 0xB001)
+        if (calculateCrc16(buf, offset) != 0xB001)
         {
             return CrcError;
         }
     }
 
     // check the second CRC16
-    if (calculateCrc16(buf, offset, (cnt - offset)) != 0xB001)
+    if (calculateCrc16(buf + offset, cnt - offset) != 0xB001)
     {
         return CrcError;
     }
@@ -1164,7 +1166,7 @@
     ISha256MacCoproc::SlaveSecretData slaveSecretData;
 
     // insert ROM number
-    std::memcpy(slaveSecretData, romId, RomId::byteLen);
+    std::memcpy(slaveSecretData.data(), romId.buffer.data(), romId.buffer.size());
 
     slaveSecretData[11] = 0x00;
     slaveSecretData[10] = bindingPageNum;
@@ -1173,3 +1175,123 @@
 
     return MacCoproc.computeSlaveSecret(ISha256MacCoproc::DevicePage(bindingPage), partialSecret, slaveSecretData);
 }
+
+template <class T, size_t N>
+OneWireSlave::CmdResult DS28E15_22_25::doReadAllBlockProtection(array<BlockProtection, N> & protection) const
+{
+    uint8_t buf[N];
+    CmdResult result = readStatus<T>(false, true, 0, buf);
+    if (result == Success)
+    {
+        for (size_t i = 0; i < N; i++)
+        {
+            protection[i].setStatusByte(buf[i]);
+        }
+    }
+    return result;
+}
+
+OneWireSlave::CmdResult DS28E15::writeScratchpad(const Scratchpad & data) const
+{
+    return doWriteScratchpad<DS28E15>(data);
+}
+
+OneWireSlave::CmdResult DS28E15::readScratchpad(Scratchpad & data) const
+{
+    return doReadScratchpad<DS28E15>(data);
+}
+
+OneWireSlave::CmdResult DS28E15::readBlockProtection(unsigned int blockNum, BlockProtection & protection) const
+{
+    return doReadBlockProtection<DS28E15>(blockNum, protection);
+}
+
+OneWireSlave::CmdResult DS28E15::readPersonality(Personality & personality) const
+{
+    return doReadPersonality<DS28E15>(personality);
+}
+
+OneWireSlave::CmdResult DS28E15::writeAuthSegment(const ISha256MacCoproc & MacCoproc, unsigned int pageNum, unsigned int segmentNum, const Segment & newData, const Segment & oldData, bool continuing)
+{
+    return doWriteAuthSegment<DS28E15>(MacCoproc, pageNum, segmentNum, newData, oldData, continuing);
+}
+
+OneWireSlave::CmdResult DS28E15::writeAuthSegmentMac(unsigned int pageNum, unsigned int segmentNum, const Segment & newData, const Mac & mac, bool continuing)
+{
+    return doWriteAuthSegmentMac<DS28E15>(pageNum, segmentNum, newData, mac, continuing);
+}
+
+OneWireSlave::CmdResult DS28E15::readAllBlockProtection(array<BlockProtection, protectionBlocks> & protection) const
+{
+    return doReadAllBlockProtection<DS28E15>(protection);
+}
+
+OneWireSlave::CmdResult DS28E22::writeScratchpad(const Scratchpad & data) const
+{
+    return doWriteScratchpad<DS28E22>(data);
+}
+
+OneWireSlave::CmdResult DS28E22::readScratchpad(Scratchpad & data) const
+{
+    return doReadScratchpad<DS28E22>(data);
+}
+
+OneWireSlave::CmdResult DS28E22::readBlockProtection(unsigned int blockNum, BlockProtection & protection) const
+{
+    return doReadBlockProtection<DS28E22>(blockNum, protection);
+}
+
+OneWireSlave::CmdResult DS28E22::readPersonality(Personality & personality) const
+{
+    return doReadPersonality<DS28E22>(personality);
+}
+
+OneWireSlave::CmdResult DS28E22::writeAuthSegment(const ISha256MacCoproc & MacCoproc, unsigned int pageNum, unsigned int segmentNum, const Segment & newData, const Segment & oldData, bool continuing)
+{
+    return doWriteAuthSegment<DS28E22>(MacCoproc, pageNum, segmentNum, newData, oldData, continuing);
+}
+
+OneWireSlave::CmdResult DS28E22::writeAuthSegmentMac(unsigned int pageNum, unsigned int segmentNum, const Segment & newData, const Mac & mac, bool continuing)
+{
+    return doWriteAuthSegmentMac<DS28E22>(pageNum, segmentNum, newData, mac, continuing);
+}
+
+OneWireSlave::CmdResult DS28E22::readAllBlockProtection(array<BlockProtection, protectionBlocks> & protection) const
+{
+    return doReadAllBlockProtection<DS28E22>(protection);
+}
+
+OneWireSlave::CmdResult DS28E25::writeScratchpad(const Scratchpad & data) const
+{
+    return doWriteScratchpad<DS28E25>(data);
+}
+
+OneWireSlave::CmdResult DS28E25::readScratchpad(Scratchpad & data) const
+{
+    return doReadScratchpad<DS28E25>(data);
+}
+
+OneWireSlave::CmdResult DS28E25::readBlockProtection(unsigned int blockNum, BlockProtection & protection) const
+{
+    return doReadBlockProtection<DS28E25>(blockNum, protection);
+}
+
+OneWireSlave::CmdResult DS28E25::readPersonality(Personality & personality) const
+{
+    return doReadPersonality<DS28E25>(personality);
+}
+
+OneWireSlave::CmdResult DS28E25::writeAuthSegment(const ISha256MacCoproc & MacCoproc, unsigned int pageNum, unsigned int segmentNum, const Segment & newData, const Segment & oldData, bool continuing)
+{
+    return doWriteAuthSegment<DS28E25>(MacCoproc, pageNum, segmentNum, newData, oldData, continuing);
+}
+
+OneWireSlave::CmdResult DS28E25::writeAuthSegmentMac(unsigned int pageNum, unsigned int segmentNum, const Segment & newData, const Mac & mac, bool continuing)
+{
+    return doWriteAuthSegmentMac<DS28E25>(pageNum, segmentNum, newData, mac, continuing);
+}
+
+OneWireSlave::CmdResult DS28E25::readAllBlockProtection(array<BlockProtection, protectionBlocks> & protection) const
+{
+    return doReadAllBlockProtection<DS28E25>(protection);
+}
\ No newline at end of file
--- a/Slaves/Authenticators/DS28E15_22_25/DS28E15_22_25.h	Fri Dec 02 19:21:55 2016 +0000
+++ b/Slaves/Authenticators/DS28E15_22_25/DS28E15_22_25.h	Tue Dec 13 13:31:30 2016 -0800
@@ -47,61 +47,7 @@
         typedef array<uint8_t, 4> Segment;
 
         /// Holds the contents of a device memory page.
-        class Page
-        {
-        public:
-            /// Length of the buffer in bytes.
-            static const size_t length = 32;
-
-        private:
-            array<uint8_t, length> m_data;
-
-        public:
-            /// Built-in array representation.
-            typedef array<uint8_t, length>::Buffer Buffer;
-
-            Page() { }
-            Page(const Page & page) : m_data(page.m_data) { }
-            Page(const Buffer & dataBytes) : m_data(dataBytes) { }
-
-            const Page & operator=(const Page & rhs)
-            {
-                this->m_data = rhs.m_data;
-                return rhs;
-            }
-
-            bool operator==(const Page & rhs) const
-            {
-                return (this->m_data == rhs.m_data);
-            }
-
-            bool operator!=(const Page & rhs) const
-            {
-                return !operator==(rhs);
-            }
-
-            /// Conversion to array reference.
-            operator Buffer &()
-            {
-                return m_data;
-            }
-
-            /// Conversion to const array reference.
-            operator const Buffer &() const
-            {
-                return m_data;
-            }
-
-            /// Creates a segment representation from a subsection of the page data.
-            /// @param segmentNum Segment number within page to copy from.
-            /// @returns The copied segment data.
-            Segment toSegment(unsigned int segmentNum) const;
-
-            /// Copies segment data to the page.
-            /// @param segmentNum Segment number within the page to copy to.
-            /// @param[in] segment Segment to copy from.
-            void fromSegment(unsigned int segmentNum, const Segment & segment);
-        };
+        typedef array<uint8_t, 32> Page;
 
         /// Holds the contents of the device scratchpad.
         typedef array<uint8_t, 32> Scratchpad;
@@ -113,17 +59,25 @@
         typedef array<uint8_t, 2> ManId;
 
         /// Container for the device personality.
-        union Personality
+        class Personality
         {
-            array<uint8_t, 4>::Buffer bytes;
-            struct
-            {
-                uint8_t PB1;
-                uint8_t PB2;
-                ManId::Buffer manIdBytes;
+        public:
+            typedef array<uint8_t, 4> Buffer;
+            
+        private:
+            Buffer m_data;
 
-                bool secretLocked() const { return (PB2 & 0x01); }
-            } fields;
+        public:
+            Personality() { }
+            explicit Personality(const Buffer & dataBytes) : m_data(dataBytes) { }
+           
+            uint8_t PB1() const { return m_data[0]; }
+            uint8_t PB2() const { return m_data[1]; }
+            ManId manId() const { ManId manId = { m_data[2], m_data[3] }; return manId; }
+            bool secretLocked() const { return (PB2() & 0x01); }
+            
+            bool operator==(const Personality & rhs) const { return (this->m_data == rhs.m_data); }
+            bool operator!=(const Personality & rhs) const { return !operator==(rhs); }
         };
 
         /// Represents the status of a memory protection block.
@@ -134,8 +88,8 @@
             uint8_t m_status;
 
         public:
-            BlockProtection() : m_status(0x00) { }
-            BlockProtection(bool readProtection, bool writeProtection, bool eepromEmulation, bool authProtection, uint8_t blockNum);
+            explicit BlockProtection(uint8_t status = 0x00) : m_status(status) { }
+            BlockProtection(bool readProtection, bool writeProtection, bool eepromEmulation, bool authProtection, unsigned int blockNum);
 
             /// Get the byte representation used by the device.
             uint8_t statusByte() const { return m_status; }
@@ -143,9 +97,9 @@
             void setStatusByte(uint8_t status) { m_status = status; }
 
             /// Get the Block Number which is indexed from zero.
-            uint8_t blockNum() const { return (m_status & blockNumMask); }
+            unsigned int blockNum() const { return (m_status & blockNumMask); }
             /// Set the Block Number which is indexed from zero.
-            void setBlockNum(uint8_t blockNum);
+            void setBlockNum(unsigned int blockNum);
 
             /// Get the Read Protection status.
             /// @returns True if Read Protection is enabled.
@@ -260,7 +214,17 @@
                                                               Mac & mac);
 
         /// Number of segments per page.
-        static const unsigned int segmentsPerPage = (Page::length / Segment::length);
+        static const unsigned int segmentsPerPage = (Page::csize / Segment::csize);
+        
+        /// Creates a segment representation from a subsection of the page data.
+        /// @param segmentNum Segment number within page to copy from.
+        /// @returns The copied segment data.
+        static Segment segmentFromPage(unsigned int segmentNum, const Page & page);
+
+        /// Copies segment data to the page.
+        /// @param segmentNum Segment number within the page to copy to.
+        /// @param[in] segment Segment to copy from.
+        static void segmentToPage(unsigned int segmentNum, const Segment & segment, Page & page);
 
         /// @{
         /// Manufacturer ID
@@ -282,16 +246,6 @@
         /// @param lock Prevent further changes to the secret on the device after loading.
         CmdResult loadSecret(bool lock);
 
-        /// Perform Write Scratchpad operation on the device.
-        /// @note 1-Wire ROM selection should have already occurred.
-        /// @param[in] data Data to write to the scratchpad.
-        CmdResult writeScratchpad(const Scratchpad & data) const;
-
-        /// Perform a Read Scratchpad operation on the device.
-        /// @note 1-Wire ROM selection should have already occurred.
-        /// @param[out] data Buffer to read data from the scratchpad into.
-        CmdResult readScratchpad(Scratchpad & data) const;
-
         /// Read memory segment using the Read Memory command on the device.
         /// @note 1-Wire ROM selection should have already occurred.
         /// @param pageNum Page number for read operation.
@@ -332,17 +286,6 @@
         /// @param[out] mac The device computed MAC.
         CmdResult computeReadPageMac(unsigned int pageNum, bool anon, Mac & mac) const;
 
-        /// Read the status of a memory protection block using the Read Status command.
-        /// @note 1-Wire ROM selection should have already occurred.
-        /// @param blockNum Block number to to read status of.
-        /// @param[out] protection Receives protection status read from device.
-        CmdResult readBlockProtection(unsigned int blockNum, BlockProtection & protection);
-
-        /// Read the personality bytes using the Read Status command.
-        /// @note 1-Wire ROM selection should have already occurred.
-        /// @param[out] personality Receives personality read from device.
-        CmdResult readPersonality(Personality & personality) const;
-
         /// Update the status of a memory protection block using the Write Page Protection command.
         /// @note 1-Wire ROM selection should have already occurred.
         /// @param[in] Desired protection status for the block.
@@ -361,68 +304,60 @@
         CmdResult writeAuthBlockProtection(const ISha256MacCoproc & MacCoproc,
                                            const BlockProtection & newProtection,
                                            const BlockProtection & oldProtection);
-
-        /// Write memory segment with authentication using the Authenticated Write Memory command.
-        /// @note 1-Wire ROM selection should have already occurred.
-        /// @param MacCoproc Coprocessor to use for Write MAC computation.
-        /// @param pageNum Page number for write operation.
-        /// @param segmentNum Segment number within page for write operation.
-        /// @param[in] newData New data to write to the segment.
-        /// @param[in] oldData Existing data contained in the segment.
-        /// @param continuing True to continue writing with the next sequential segment.
-        ///                   False to begin a new command.
-        CmdResult writeAuthSegment(const ISha256MacCoproc & MacCoproc,
-                                   unsigned int pageNum,
-                                   unsigned int segmentNum,
-                                   const Segment & newData,
-                                   const Segment & oldData,
-                                   bool continuing = false);
-
-        /// Write memory segment with authentication using the Authenticated Write Memory command.
-        /// @note 1-Wire ROM selection should have already occurred.
-        /// @param pageNum Page number for write operation.
-        /// @param segmentNum Segment number within page for write operation.
-        /// @param[in] newData New data to write to the segment.
-        /// @param[in] mac Write MAC computed for this operation.
-        /// @param continuing True to continue writing with the next sequential segment.
-        ///                   False to begin a new command.
-        CmdResult writeAuthSegmentMac(unsigned int pageNum,
-                                      unsigned int segmentNum,
-                                      const Segment & newData,
-                                      const Mac & mac,
-                                      bool continuing = false);
                                       
-    protected:
-        /// Family code for each device.
-        enum FamilyCode
-        {
-            DS28E25_Family = 0x47,
-            DS28E22_Family = 0x48,
-            DS28E15_Family = 0x17
-        };
-    
+    protected:    
         /// @param owMaster 1-Wire Master to use for communication with DS28E15/22/25.
         /// @param lowVoltage Enable low voltage timing.
-        DS28E15_22_25(RandomAccessRomIterator & selector, bool lowVoltage, FamilyCode variant);
+        DS28E15_22_25(RandomAccessRomIterator & selector, bool lowVoltage);
         
         ~DS28E15_22_25() { }
+        
+        template <class T>
+        CmdResult doWriteScratchpad(const Scratchpad & data) const;
+
+        template <class T>
+        CmdResult doReadScratchpad(Scratchpad & data) const;
+        
+        template <class T>
+        CmdResult doReadBlockProtection(unsigned int blockNum, BlockProtection & protection) const;
+
+        template <class T>
+        CmdResult doReadPersonality(Personality & personality) const;
+        
+        template <class T>
+        CmdResult doWriteAuthSegment(const ISha256MacCoproc & MacCoproc,
+                                     unsigned int pageNum,
+                                     unsigned int segmentNum,
+                                     const Segment & newData,
+                                     const Segment & oldData,
+                                     bool continuing);
+
+        template <class T>
+        CmdResult doWriteAuthSegmentMac(unsigned int pageNum,
+                                        unsigned int segmentNum,
+                                        const Segment & newData,
+                                        const Mac & mac,
+                                        bool continuing);
+        
+        template <class T, size_t N>
+        CmdResult doReadAllBlockProtection(array<BlockProtection, N> & protection) const;
 
     private:
-        ManId m_manId;
-        bool m_lowVoltage;
-        const FamilyCode m_variant;
-    
-        static const unsigned int shaComputationDelayMs = 3;
-        static const unsigned int eepromWriteDelayMs = 10;
-        unsigned int secretEepromWriteDelayMs() const { return (m_lowVoltage ? 200 : 100); }
-
         /// Read status bytes which are either personality or block protection.
         /// @note 1-Wire ROM selection should have already occurred.
         /// @param personality True to read personality or false to read block protection.
         /// @param allpages True to read all pages or false to read one page.
         /// @param pageNum Page number if reading block protection.
         /// @param rdbuf Buffer to receive data read from device.
+        template <class T>
         CmdResult readStatus(bool personality, bool allpages, unsigned int blockNum, uint8_t * rdbuf) const;
+    
+        ManId m_manId;
+        bool m_lowVoltage;
+    
+        static const unsigned int shaComputationDelayMs = 3;
+        static const unsigned int eepromWriteDelayMs = 10;
+        unsigned int secretEepromWriteDelayMs() const { return (m_lowVoltage ? 200 : 100); }
     };
 }
 
--- a/Slaves/Authenticators/DS28E15_22_25/DS28E22.h	Fri Dec 02 19:21:55 2016 +0000
+++ b/Slaves/Authenticators/DS28E15_22_25/DS28E22.h	Tue Dec 13 13:31:30 2016 -0800
@@ -36,15 +36,75 @@
 #include "DS28E15_22_25.h"
 
 namespace OneWire
-{
+{    
     /// Interface to the DS28E22 and DS28EL22 (low power) authenticators.
     class DS28E22 : public DS28E15_22_25
     {
-    public:    
+    public:       
+        // DS28E15_22_25 traits
+        static const unsigned int memoryPages = 8;
+        static const unsigned int protectionBlocks = 4;
+    
         /// @param owMaster 1-Wire Master to use for communication with DS28E15.
         /// @param lowVoltage Enable low voltage timing.
         DS28E22(RandomAccessRomIterator & selector, bool lowVoltage = false)
-            : DS28E15_22_25(selector, lowVoltage, DS28E22_Family) { }
+            : DS28E15_22_25(selector, lowVoltage) { }
+            
+        /// Perform Write Scratchpad operation on the device.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param[in] data Data to write to the scratchpad.
+        CmdResult writeScratchpad(const Scratchpad & data) const;
+
+        /// Perform a Read Scratchpad operation on the device.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param[out] data Buffer to read data from the scratchpad into.
+        CmdResult readScratchpad(Scratchpad & data) const;
+        
+        /// Read the status of a memory protection block using the Read Status command.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param blockNum Block number to to read status of.
+        /// @param[out] protection Receives protection status read from device.
+        CmdResult readBlockProtection(unsigned int blockNum, BlockProtection & protection) const;
+
+        /// Read the personality bytes using the Read Status command.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param[out] personality Receives personality read from device.
+        CmdResult readPersonality(Personality & personality) const;
+        
+        /// Write memory segment with authentication using the Authenticated Write Memory command.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param MacCoproc Coprocessor to use for Write MAC computation.
+        /// @param pageNum Page number for write operation.
+        /// @param segmentNum Segment number within page for write operation.
+        /// @param[in] newData New data to write to the segment.
+        /// @param[in] oldData Existing data contained in the segment.
+        /// @param continuing True to continue writing with the next sequential segment.
+        ///                   False to begin a new command.
+        CmdResult writeAuthSegment(const ISha256MacCoproc & MacCoproc,
+                                   unsigned int pageNum,
+                                   unsigned int segmentNum,
+                                   const Segment & newData,
+                                   const Segment & oldData,
+                                   bool continuing = false);
+
+        /// Write memory segment with authentication using the Authenticated Write Memory command.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param pageNum Page number for write operation.
+        /// @param segmentNum Segment number within page for write operation.
+        /// @param[in] newData New data to write to the segment.
+        /// @param[in] mac Write MAC computed for this operation.
+        /// @param continuing True to continue writing with the next sequential segment.
+        ///                   False to begin a new command.
+        CmdResult writeAuthSegmentMac(unsigned int pageNum,
+                                      unsigned int segmentNum,
+                                      const Segment & newData,
+                                      const Mac & mac,
+                                      bool continuing = false);
+            
+        /// Read the status of all memory protection blocks using the Read Status command.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param[out] protection Receives protection statuses read from device.    
+        CmdResult readAllBlockProtection(array<BlockProtection, protectionBlocks> & protection) const;
     };
 }
 
--- a/Slaves/Authenticators/DS28E15_22_25/DS28E25.h	Fri Dec 02 19:21:55 2016 +0000
+++ b/Slaves/Authenticators/DS28E15_22_25/DS28E25.h	Tue Dec 13 13:31:30 2016 -0800
@@ -36,15 +36,75 @@
 #include "DS28E15_22_25.h"
 
 namespace OneWire
-{
+{    
     /// Interface to the DS28E25 and DS28EL25 (low power) authenticators.
     class DS28E25 : public DS28E15_22_25
     {
-    public:    
+    public:        
+        // DS28E15_22_25 traits
+        static const unsigned int memoryPages = 16;
+        static const unsigned int protectionBlocks = 8;
+    
         /// @param owMaster 1-Wire Master to use for communication with DS28E15.
         /// @param lowVoltage Enable low voltage timing.
         DS28E25(RandomAccessRomIterator & selector, bool lowVoltage = false)
-            : DS28E15_22_25(selector, lowVoltage, DS28E25_Family) { }
+            : DS28E15_22_25(selector, lowVoltage) { }
+            
+        /// Perform Write Scratchpad operation on the device.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param[in] data Data to write to the scratchpad.
+        CmdResult writeScratchpad(const Scratchpad & data) const;
+
+        /// Perform a Read Scratchpad operation on the device.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param[out] data Buffer to read data from the scratchpad into.
+        CmdResult readScratchpad(Scratchpad & data) const;
+        
+        /// Read the status of a memory protection block using the Read Status command.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param blockNum Block number to to read status of.
+        /// @param[out] protection Receives protection status read from device.
+        CmdResult readBlockProtection(unsigned int blockNum, BlockProtection & protection) const;
+
+        /// Read the personality bytes using the Read Status command.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param[out] personality Receives personality read from device.
+        CmdResult readPersonality(Personality & personality) const;
+        
+        /// Write memory segment with authentication using the Authenticated Write Memory command.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param MacCoproc Coprocessor to use for Write MAC computation.
+        /// @param pageNum Page number for write operation.
+        /// @param segmentNum Segment number within page for write operation.
+        /// @param[in] newData New data to write to the segment.
+        /// @param[in] oldData Existing data contained in the segment.
+        /// @param continuing True to continue writing with the next sequential segment.
+        ///                   False to begin a new command.
+        CmdResult writeAuthSegment(const ISha256MacCoproc & MacCoproc,
+                                   unsigned int pageNum,
+                                   unsigned int segmentNum,
+                                   const Segment & newData,
+                                   const Segment & oldData,
+                                   bool continuing = false);
+
+        /// Write memory segment with authentication using the Authenticated Write Memory command.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param pageNum Page number for write operation.
+        /// @param segmentNum Segment number within page for write operation.
+        /// @param[in] newData New data to write to the segment.
+        /// @param[in] mac Write MAC computed for this operation.
+        /// @param continuing True to continue writing with the next sequential segment.
+        ///                   False to begin a new command.
+        CmdResult writeAuthSegmentMac(unsigned int pageNum,
+                                      unsigned int segmentNum,
+                                      const Segment & newData,
+                                      const Mac & mac,
+                                      bool continuing = false);
+            
+        /// Read the status of all memory protection blocks using the Read Status command.
+        /// @note 1-Wire ROM selection should have already occurred.
+        /// @param[out] protection Receives protection statuses read from device.    
+        CmdResult readAllBlockProtection(array<BlockProtection, protectionBlocks> & protection) const;
     };
 }
 
--- a/Slaves/Bridges/DS28E17/DS28E17.h	Fri Dec 02 19:21:55 2016 +0000
+++ b/Slaves/Bridges/DS28E17/DS28E17.h	Tue Dec 13 13:31:30 2016 -0800
@@ -287,8 +287,8 @@
         *
         * On Entry:
         * @param[in]  I2C_addr
-        * Writes I2C address. The least significant bit of the I2C address
-        * is automatically cleared by the command.
+        * Defines the 7-bit I2C address to be written. 
+        * The least significant bit must be set, indicating an I2C read.
         *
         * On Exit:
         * @param[out] nu_bytes_read
--- a/Slaves/Memory/DS2431/DS2431.cpp	Fri Dec 02 19:21:55 2016 +0000
+++ b/Slaves/Memory/DS2431/DS2431.cpp	Tue Dec 13 13:31:30 2016 -0800
@@ -69,10 +69,10 @@
         
         if(startOffset != 0)
         {
-            result = this->readMemory(startRowAddress, scratchpadData, 8);
+            result = this->readMemory(startRowAddress, scratchpadData.data(), 8);
             if(result == OneWireSlave::Success)
             {
-                std::memcpy((scratchpadData + startOffset), data, (8 - startOffset));
+                std::memcpy((scratchpadData.data() + startOffset), data, (8 - startOffset));
                 result = this->writeScratchpad(startRowAddress, scratchpadData);
                 if(result == OneWireSlave::Success)
                 {
@@ -91,7 +91,7 @@
         {
             for(uint16_t row = startRowAddress; row < endRowAddress; row += 8)
             {
-                std::memcpy(scratchpadData, dataIdx, 8);
+                std::memcpy(scratchpadData.data(), dataIdx, 8);
                 
                 result = this->writeScratchpad(row, scratchpadData);
                 if(result != OneWireSlave::Success)
@@ -119,10 +119,10 @@
         {
             if(endOffset != 0)
             {
-                result = this->readMemory(endRowAddress, scratchpadData, 8);
+                result = this->readMemory(endRowAddress, scratchpadData.data(), 8);
                 if(result == OneWireSlave::Success)
                 {
-                    std::memcpy(scratchpadData, dataIdx, endOffset);
+                    std::memcpy(scratchpadData.data(), dataIdx, endOffset);
                     result = this->writeScratchpad(endRowAddress, scratchpadData);
                     if(result == OneWireSlave::Success)
                     {
@@ -178,7 +178,7 @@
         sendBlock[0] = WRITE_SCRATCHPAD;
         sendBlock[1] = (targetAddress &0xFF);
         sendBlock[2] = ((targetAddress >> 8) &0xFF);
-        std::memcpy((sendBlock + 3), data, 8);
+        std::memcpy((sendBlock + 3), data.data(), 8);
         
         owmResult = master().OWWriteBlock(sendBlock, 11);
         
@@ -190,7 +190,7 @@
         invCRC16 |= (recvbyte << 8); 
         
         //calc our own inverted CRC16 to compare with one returned
-        uint16_t calculatedInvCRC16 = ~calculateCrc16(sendBlock, 0, 11);
+        uint16_t calculatedInvCRC16 = ~calculateCrc16(sendBlock, 11);
         
         if(invCRC16 == calculatedInvCRC16)
         {
@@ -225,12 +225,12 @@
             recvBlock[0] = READ_SCRATCHPAD;
             
             //calc our own inverted CRC16 to compare with one returned
-            uint16_t calculatedInvCRC16 = ~calculateCrc16(recvBlock, 0, 12);
+            uint16_t calculatedInvCRC16 = ~calculateCrc16(recvBlock, 12);
             
             if(invCRC16 == calculatedInvCRC16)
             {
                 esByte = recvBlock[3];
-                std::memcpy(data, (recvBlock + 4), 8);
+                std::memcpy(data.data(), (recvBlock + 4), 8);
                 result = OneWireSlave::Success;
             }
         }
--- a/Utilities/array.h	Fri Dec 02 19:21:55 2016 +0000
+++ b/Utilities/array.h	Tue Dec 13 13:31:30 2016 -0800
@@ -35,6 +35,8 @@
 
 #include <stdint.h>
 #include <stddef.h>
+#include <iterator>
+#include <algorithm>
 #include <cstring>
 
 namespace OneWire
@@ -44,58 +46,55 @@
     class array
     {
     public:
-        /// Number of elements contained in the array.
-        static const size_t length = N;
-
-        /// Built-in array representation.
-        typedef T Buffer[N];
-
-    private:
-        Buffer m_buffer;
-
-    public:
-        const array<T, N> & operator=(const array<T, N> & rhs)
-        {
-            if (this != &rhs)
-            {
-                std::memcpy(this->m_buffer, rhs.m_buffer, N * sizeof(T));
-            }
-            return rhs;
-        }
-
-        bool operator==(const array<T, N> & rhs) const
-        {
-            return (std::memcmp(this->m_buffer, rhs.m_buffer, N * sizeof(T)) == 0);
-        }
-
-        bool operator!=(const array<T, N> & rhs) const
-        {
-            return !operator==(rhs);
-        }
-
-        /// Conversion to array reference.
-        operator Buffer &()
-        {
-            return m_buffer;
-        }
-
-        /// Conversion to const array reference.
-        operator const Buffer &() const
-        {
-            return m_buffer;
-        }
-
-        array<T, N>() { }
-
-        array<T, N>(const array<T, N> & copy)
-        {
-            operator=(copy);
-        }
-
-        array<T, N>(const Buffer & buffer)
-        {
-            std::memcpy(m_buffer, buffer, N * sizeof(T));
-        }
+        typedef T value_type;
+        typedef size_t size_type;
+        typedef ptrdiff_t difference_type;
+        typedef value_type & reference;
+        typedef const value_type & const_reference;
+        typedef value_type * pointer;
+        typedef const value_type * const_pointer;
+        typedef pointer iterator;
+        typedef const_pointer const_iterator;
+        typedef std::reverse_iterator<iterator> reverse_iterator;
+        typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+        
+        // Element access
+        reference operator[](size_t pos) { return _buffer[pos]; }
+        const_reference operator[](size_t pos) const { return _buffer[pos]; }
+        reference front() { return const_cast<reference>(static_cast<const array<T, N> &>(*this).front()); }
+        const_reference front() const { return _buffer[0]; }
+        reference back() { return const_cast<reference>(static_cast<const array<T, N> &>(*this).back()); }
+        const_reference back() const { return _buffer[N - 1]; }
+        T * data() { return const_cast<T *>(static_cast<const array<T, N> &>(*this).data()); }
+        const T * data() const { return _buffer; }
+        
+        // Iterators
+        iterator begin() { return const_cast<iterator>(static_cast<const array<T, N> &>(*this).begin()); }
+        const_iterator begin() const { return cbegin(); }
+        const_iterator cbegin() const { return &front(); }
+        iterator end() { return const_cast<iterator>(static_cast<const array<T, N> &>(*this).end()); }
+        const_iterator end() const { return cend(); }
+        const_iterator cend() const { return &_buffer[N]; }
+        reverse_iterator rbegin() { return reverse_iterator(&back()); }
+        const_reverse_iterator rbegin() const { return crbegin(); }
+        const_reverse_iterator crbegin() const { return const_reverse_iterator(&back()); }
+        reverse_iterator rend() { return reverse_iterator(--begin()); }
+        const_reverse_iterator rend() const { return crend(); }
+        const_reverse_iterator crend() const { return const_reverse_iterator(--begin()); }
+        
+        // Capacity
+        static bool empty() { return size() == 0; }
+        static size_type size() { return N; }
+        static size_type max_size() { return size(); }
+        static const size_type csize = N; ///< Alternative to size() when a constant expression is required.
+        
+        // Operations
+        void fill(const T & value) { std::fill(begin(), end(), value); }
+        
+        bool operator==(const array<T, N> & rhs) const { return (std::memcmp(this->_buffer, rhs._buffer, N * sizeof(T)) == 0); }
+        bool operator!=(const array<T, N> & rhs) const { return !operator==(rhs); }
+        
+        T _buffer[N];
     };
 }
 
--- a/Utilities/crc.cpp	Fri Dec 02 19:21:55 2016 +0000
+++ b/Utilities/crc.cpp	Tue Dec 13 13:31:30 2016 -0800
@@ -84,9 +84,9 @@
             return crc16;
         }
 
-        uint16_t calculateCrc16(const uint8_t * data, size_t dataOffset, size_t dataLen, uint16_t crc)
+        uint16_t calculateCrc16(const uint8_t * data, size_t dataLen, uint16_t crc)
         {
-            for (size_t i = dataOffset; i < (dataLen + dataOffset); i++)
+            for (size_t i = 0; i < dataLen; i++)
             {
                 crc = calculateCrc16(crc, data[i]);
             }
--- a/Utilities/crc.h	Fri Dec 02 19:21:55 2016 +0000
+++ b/Utilities/crc.h	Tue Dec 13 13:31:30 2016 -0800
@@ -65,7 +65,7 @@
         /// @param data_len Length of the data array to process.
         /// @param crc Beginning state of the CRC generator.
         /// @returns The calculated CRC16.
-        uint16_t calculateCrc16(const uint8_t * data, size_t dataOffset, size_t dataLen, uint16_t crc = 0);
+        uint16_t calculateCrc16(const uint8_t * data, size_t dataLen, uint16_t crc = 0);
     }
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/type_traits.h	Tue Dec 13 13:31:30 2016 -0800
@@ -0,0 +1,54 @@
+/******************************************************************//**
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+**********************************************************************/
+
+#ifndef OneWire_type_traits
+#define OneWire_type_traits
+
+namespace OneWire
+{
+    template <typename T, T v>
+    struct integral_constant
+    {
+      static const T value = v;
+      typedef T value_type;
+      typedef integral_constant<T, v> type;
+      operator T() { return v; }
+    };
+
+    typedef integral_constant<bool, true> true_type;
+    typedef integral_constant<bool, false> false_type;
+    
+    template<class T, class U> struct is_same : false_type { };
+    template<class T> struct is_same<T, T> : true_type { };
+}
+
+#endif