Implementation of 1-Wire with added Alarm Search Functionality

Dependents:   Max32630_One_Wire_Interface

Revision:
25:bdb1c5a53b58
Child:
27:d5aaefa252f1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OneWire_Memory/Authenticators/DS28E15_22_25/DS28E15_22_25.cpp	Tue Mar 22 15:18:00 2016 -0500
@@ -0,0 +1,1117 @@
+//------------Copyright (C) 2013 Maxim Integrated Products --------------
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL MAXIM INTEGRATED PRODCUTS BE LIABLE FOR ANY CLAIM, DAMAGES
+// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// Except as contained in this notice, the name of Maxim Integrated Products
+// shall not be used except as stated in the Maxim Integrated Products
+// Branding Policy.
+// ---------------------------------------------------------------------------
+
+#include "DS28E15_22_25.hpp"
+#include "mbed.h"
+
+// delay durations
+#ifdef LOW_VOLTAGE
+#define SHA_COMPUTATION_DELAY    4   
+#define EEPROM_WRITE_DELAY       15  
+#define SECRET_EEPROM_DELAY      200
+#else
+#define SHA_COMPUTATION_DELAY    3   
+#define EEPROM_WRITE_DELAY       10  
+#define SECRET_EEPROM_DELAY      90
+#endif
+
+// 1-Wire commands
+#define CMD_WRITE_MEMORY         0x55
+#define CMD_READ_MEMORY          0xF0
+#define CMD_LOAD_LOCK_SECRET     0x33
+#define CMD_COMPUTE_LOCK_SECRET  0x3C
+#define CMD_SELECT_SECRET        0x0F
+#define CMD_COMPUTE_PAGEMAC      0xA5
+#define CMD_READ_STATUS          0xAA
+#define CMD_WRITE_BLOCK_PROTECT  0xC3
+#define CMD_WRITE_AUTH_MEMORY    0x5A
+#define CMD_WRITE_AUTH_PROTECT   0xCC
+#define CMD_PIO_READ             0xDD
+#define CMD_PIO_WRITE            0x96
+
+#define BLOCK_READ_PROTECT       0x80
+#define BLOCK_WRITE_PROTECT      0x40
+#define BLOCK_EPROM_PROTECT      0x20
+#define BLOCK_WRITE_AUTH_PROTECT 0x10
+
+#define PROT_BIT_AUTHWRITE 0x10
+#define PROT_BIT_EPROM     0x20
+#define PROT_BIT_WRITE     0x40
+#define PROT_BIT_READ      0x80
+
+DS28E15_22_25::DS28E15_22_25(OneWireMaster& OW_master)
+  : m_OW_master(OW_master)
+{
+  std::memset(manId, 0x00, manIdLen);
+}
+
+DS28E15_22_25::DevicePages DS28E15_22_25::devicePages()
+{
+  DevicePages pages;
+  
+  switch (romId.familyCode())
+  {
+  case DS28E25_FAMILY:
+    pages = DS28E25_PAGES;
+    break;
+    
+  case DS28E22_FAMILY:
+    pages = DS28E22_PAGES;
+    break;
+    
+  case DS28E15_FAMILY:
+    pages = DS28E15_PAGES;
+    break;
+    
+  default:
+    pages = UNKNOWN_PAGES;
+    break;
+  }
+  
+  return pages;
+}
+
+DS28E15_22_25::DeviceBlocks DS28E15_22_25::deviceBlocks()
+{
+  DeviceBlocks blocks;
+  
+  switch (romId.familyCode())
+  {
+  case DS28E25_FAMILY:
+    blocks = DS28E25_BLOCKS;
+    break;
+    
+  case DS28E22_FAMILY:
+    blocks = DS28E22_BLOCKS;
+    break;
+    
+  case DS28E15_FAMILY:
+    blocks = DS28E15_BLOCKS;
+    break;
+    
+  default:
+    blocks = UNKNOWN_BLOCKS;
+    break;
+  }
+  
+  return blocks;
+}
+
+//--------------------------------------------------------------------------
+//  Write page protection byte. 
+// 
+//  Parameters
+//     block - block number (0 to 7) which covers two pages each
+//     new_value - new protection byte
+//     old_value - old protection byte
+//     manid - manufacturer ID
+//     contflag - Flag to indicate the write is continued from the last
+//
+//  Returns: true - protection written
+//           false - Failed to set protection
+//
+OneWireSlave::CmdResult DS28E15_22_25::WriteAuthBlockProtection(const ISha256MacCoprocessor & MacCoproc, std::uint8_t newProtection, std::uint8_t oldProtection, bool contflag)	
+{
+   std::uint8_t buf[256], cs;
+   int cnt = 0;
+
+   buf[cnt++] = CMD_WRITE_AUTH_PROTECT;
+   buf[cnt++] = newProtection;
+
+   // Send command
+   m_OW_master.OWWriteBlock(&buf[0], 2);
+
+   // read first CRC byte
+   m_OW_master.OWReadByte(buf[cnt++]);
+
+   // read the last CRC and enable
+   m_OW_master.OWReadBytePower(buf[cnt++]);
+
+   // now wait for the MAC computation.
+   wait_ms(SHA_COMPUTATION_DELAY);
+
+   // disable strong pullup
+   m_OW_master.OWLevel(OneWireMaster::LEVEL_NORMAL);
+   
+   // check CRC16
+   if (OneWireMaster::calculateCRC16(buf, 0, cnt) != 0xB001)
+      return CommunicationError;
+
+   ISha256MacCoprocessor::CmdResult result;
+   result = CalculateProtectionWriteMAC256(MacCoproc, newProtection, oldProtection, romId, manId, reinterpret_cast<std::uint8_t (&)[macLen]>(buf));
+   if (result != ISha256MacCoprocessor::Success)
+     return OperationFailure;
+   cnt = macLen;
+
+   // send the MAC
+   m_OW_master.OWWriteBlock(&buf[0], macLen);
+
+   // Read CRC and CS byte
+   m_OW_master.OWReadBlock(&buf[cnt], 3);
+   cnt += 3;
+
+   // ckeck CRC16
+   if (OneWireMaster::calculateCRC16(buf, 0, (cnt - 1)) != 0xB001)
+      return CommunicationError;
+
+   // check CS
+   if (buf[cnt-1] != 0xAA)
+      return OperationFailure;
+   
+   // send release and strong pull-up
+   // DATASHEET_CORRECTION - last bit in release is a read-zero so don't check echo of write byte
+   m_OW_master.OWWriteBytePower(0xAA);
+
+   // now wait for the MAC computation.
+   wait_ms(EEPROM_WRITE_DELAY);
+
+   // disable strong pullup
+   m_OW_master.OWLevel(OneWireMaster::LEVEL_NORMAL);
+
+   // read the CS byte
+   m_OW_master.OWReadByte(cs);
+
+   if (cs == 0xAA)
+     return Success;
+   // else
+   return OperationFailure;
+}
+
+//--------------------------------------------------------------------------
+//  Write page protection byte. 
+// 
+//  Parameters
+//     block - block number (0 to 7) which covers two pages each
+//     prot - protection byte
+//     contflag - Flag to indicate the write is continued from the last
+//
+//  Returns: true - protection written
+//           false - Failed to set protection
+//
+OneWireSlave::CmdResult DS28E15_22_25::WriteBlockProtection(std::uint8_t protection, bool continuing)	
+{
+   std::uint8_t buf[256], cs;
+   int cnt = 0;
+
+   // check if not continuing a previous block write
+   if (!continuing)
+   {
+      buf[cnt++] = CMD_WRITE_BLOCK_PROTECT;
+   }
+
+   // compute parameter byte 
+   buf[cnt++] = protection;
+
+   m_OW_master.OWWriteBlock(&buf[0], cnt);
+
+   // Read CRC
+   m_OW_master.OWReadBlock(&buf[cnt], 2);
+   cnt += 2;
+
+   // check CRC16
+   if (OneWireMaster::calculateCRC16(buf, 0, cnt) != 0xB001)
+      return CommunicationError;
+
+   // DATASHEET_CORRECTION, on continue need second release byte    
+   if (continuing)
+      m_OW_master.OWWriteByte(0xAA);
+
+   // sent release
+   m_OW_master.OWWriteBytePower(0xAA);
+
+   // now wait for programming
+   wait_ms(EEPROM_WRITE_DELAY);
+
+   // disable strong pullup
+   m_OW_master.OWLevel(OneWireMaster::LEVEL_NORMAL);
+
+   // read the CS byte
+   m_OW_master.OWReadByte(cs);
+
+   if (cs == 0xAA)
+     return Success;
+   // else
+   return OperationFailure;
+}
+
+
+
+
+OneWireSlave::CmdResult DS28E15_22_25::ReadBlockProtectionStatus(unsigned int blockNum, std::uint8_t & status)
+{
+  unsigned char buf;
+  CmdResult result = ReadStatus(false, false, blockNum, &buf);
+  if (result == Success)
+    status = buf;
+  return result;
+}
+
+//--------------------------------------------------------------------------
+//  Read status bytes, either personality or page protection. 
+// 
+//  Parameters
+//     personality - flag to indicate the read is the 4 personality bytes (true)
+//                  or page page protection (false)
+//     allpages - flag to indicate if just one page (false) or all (true) page protection 
+//                 bytes. 
+//     page_num - page number if reading protection 0 to 1
+//     rdbuf - 16 byte buffer personality bytes (length 4) or page protection 
+//            (length 1 or 16) 
+//
+//  Returns: true - status read
+//           false - Failed to read status
+//
+OneWireSlave::CmdResult DS28E15_22_25::ReadStatus(bool personality, bool allpages, unsigned int pageNum, unsigned char *rdbuf) const
+{
+   unsigned char buf[256];
+   int cnt, offset, rdnum;
+
+   cnt = 0;
+   offset = 0;
+
+   buf[cnt++] = CMD_READ_STATUS;   
+   if (personality)
+      buf[cnt++] = 0xE0;
+   else if (!allpages)
+      buf[cnt++] = pageNum;
+   else
+      buf[cnt++] = 0;  
+
+   // send the command
+   m_OW_master.OWWriteBlock(&buf[0], 2);
+
+   offset = cnt + 2;
+
+   // adjust data length
+   if ((romId.familyCode() == DS28E25_FAMILY) || (romId.familyCode() == DS28E22_FAMILY))
+   {
+      if (personality)
+         rdnum = 8;
+      else if (allpages)
+         rdnum = 20;
+      else
+         rdnum = 5;
+   }
+   else
+   {
+      if ((personality) || (allpages))
+         rdnum = 8;
+      else
+         rdnum = 5;
+   }
+
+   // Read the bytes 
+   m_OW_master.OWReadBlock(&buf[cnt],rdnum);
+   cnt += rdnum;
+
+   // check the first CRC16
+   if (OneWireMaster::calculateCRC16(buf, 0, offset) != 0xB001)
+      return CommunicationError;
+
+   if ((((romId.familyCode() == DS28E25_FAMILY) || (romId.familyCode() == DS28E22_FAMILY)) 
+        && (allpages || (pageNum == 15))) ||
+       (personality || allpages || (pageNum == 1)))
+   {
+      // check the second CRC16
+      if (OneWireMaster::calculateCRC16(buf, offset, (cnt - offset)) != 0xB001)
+         return CommunicationError;
+   }
+
+   // copy the data to the read buffer
+   memcpy(rdbuf, &buf[offset], rdnum - 4);
+
+   return Success;
+}
+
+
+
+
+ISha256MacCoprocessor::CmdResult DS28E15_22_25::CalculateAuthMAC256(const ISha256MacCoprocessor & MacCoproc, unsigned int pageNum, const std::uint8_t (&challenge)[scratchpadSize], const std::uint8_t (&pageData)[pageSize], const RomId & romId, const std::uint8_t (&manId)[manIdLen], bool anon, std::uint8_t (&mac)[macLen])
+{
+   std::uint8_t pageBuf[pageSize], challengeBuf[scratchpadSize], AuthMAC_data[ISha256MacCoprocessor::AuthMAC_data_len];
+
+   // insert page data
+   std::memcpy(pageBuf, pageData, pageSize);
+
+   // insert challenge
+   std::memcpy(challengeBuf, challenge, scratchpadSize);
+   
+   // insert ROM number or FF
+   if (anon)
+     std::memset(AuthMAC_data, 0xFF, RomId::byteLen);
+   else
+     std::memcpy(AuthMAC_data, romId, RomId::byteLen);
+
+   AuthMAC_data[10] = pageNum;
+
+   AuthMAC_data[9] = manId[0];
+   AuthMAC_data[8] = manId[1];
+   
+   AuthMAC_data[11] = 0x00;
+
+   return MacCoproc.ComputeAndRead_AuthMAC(pageBuf, challengeBuf, AuthMAC_data, mac);
+}
+
+//--------------------------------------------------------------------------
+//  Verify provided MAC and page data. Optionally do
+//  annonymous mode (anon != 0). 
+// 
+//  Parameters
+//     page_num - page number to read 0 - 16
+//     challange - 32 byte buffer containing the challenge
+//     page_data - 32 byte buffer to contain the data read
+//     manid - 2 byte buffer containing the manufacturer ID (general device: 00h,00h)
+//     mac - 32 byte buffer of mac read
+//     anon - Flag to indicate Annonymous mode
+//
+//  Returns: true - page read has correct MAC
+//           false - Failed to read page or incorrect MAC
+//
+ISha256MacCoprocessor::CmdResult DS28E15_22_25::AuthVerify(const ISha256MacCoprocessor & MacCoproc, unsigned int page_num, const std::uint8_t (&challenge)[scratchpadSize], const std::uint8_t (&pageData)[pageSize], const RomId & romId, const std::uint8_t (&manId)[manIdLen], bool anon, const std::uint8_t (&mac)[macLen])	
+{
+  std::uint8_t calc_mac[macLen];
+  ISha256MacCoprocessor::CmdResult result;
+  result = CalculateAuthMAC256(MacCoproc, page_num, challenge, pageData, romId, manId, anon, calc_mac);
+  if (result == ISha256MacCoprocessor::Success)
+  {
+   if (memcmp(mac, calc_mac, macLen) != 0)
+     result = ISha256MacCoprocessor::OperationFailure;
+  }
+  return result;
+}
+
+//--------------------------------------------------------------------------
+//  Do Compute Page MAC command and return MAC. Optionally do
+//  annonymous mode (anon != 0). 
+// 
+//  Parameters
+//     sn  - secret number 0 or 1
+//     page_num - page number to read 0 - 16
+//     challange - 32 byte buffer containing the challenge
+//     mac - 32 byte buffer for page data read
+//     anon - Flag to indicate Annonymous mode
+//
+//  Returns: true - page read has correct MAC
+//           false - Failed to read page or incorrect MAC
+//
+OneWireSlave::CmdResult DS28E15_22_25::ComputeReadPageMAC(unsigned int page_num, bool anon, std::uint8_t (&mac)[macLen]) const	
+{
+   std::uint8_t buf[256],cs;
+   int cnt = 0;
+
+   buf[cnt++] = CMD_COMPUTE_PAGEMAC;                 
+   buf[cnt++] = ((anon) ? 0xE0 : 0x00) | page_num;  
+
+   // Send command
+   m_OW_master.OWWriteBlock(&buf[0], 2);
+
+   // read first CRC byte
+   m_OW_master.OWReadByte(buf[cnt++]);
+
+   // read the last CRC and enable
+   m_OW_master.OWReadBytePower(buf[cnt++]);
+
+   // now wait for the MAC computation.
+   wait_ms(SHA_COMPUTATION_DELAY * 2);
+
+   // disable strong pullup
+   m_OW_master.OWLevel(OneWireMaster::LEVEL_NORMAL);
+
+   // check CRC16
+   if (OneWireMaster::calculateCRC16(buf, 0, cnt) != 0xB001)
+      return CommunicationError;
+
+   // read the CS byte
+   m_OW_master.OWReadByte(cs);
+   if (cs != 0xAA)
+      return OperationFailure;
+
+   // read the MAC and CRC
+   m_OW_master.OWReadBlock(&buf[0], (macLen + 2));
+
+   // check CRC16
+   if (OneWireMaster::calculateCRC16(buf, 0, (macLen + 2)) != 0xB001)
+      return CommunicationError;      
+
+   // copy MAC to return buffer
+   memcpy(mac, buf, macLen);
+
+   return Success;
+}
+
+//----------------------------------------------------------------------
+// Compute secret operation on the DS28E25/DS28E22/DS28E15.
+//
+// 'sn'        - secret number 0 or 1
+// 'partial'   - partial secret to load (32 bytes)
+// 'pagedata'  - page data to compute (32 bytes)
+// 'lock'      - option to lock the secret after the load (lock = true)
+//
+// Return: true - load complete
+//         false - error during load, device not present
+//
+OneWireSlave::CmdResult DS28E15_22_25::ComputeSecret(unsigned int page_num, bool lock) 
+{
+  std::uint8_t buf[256], cs;
+  int cnt = 0;
+
+  buf[cnt++] = CMD_COMPUTE_LOCK_SECRET;                 
+  buf[cnt++] = (lock) ? (0xE0 | page_num) : page_num;  // lock flag 
+
+  // Send command
+  m_OW_master.OWWriteBlock(&buf[0], 2);
+
+  // Read CRC
+  m_OW_master.OWReadBlock(&buf[cnt], 2);
+  cnt += 2;
+
+  // check CRC16
+  if (OneWireMaster::calculateCRC16(buf, 0, cnt) != 0xB001)
+    return CommunicationError;
+
+  // send release and strong pull-up
+  m_OW_master.OWWriteBytePower(0xAA);
+
+  // now wait for the MAC computation.
+  wait_ms(SHA_COMPUTATION_DELAY * 2 + SECRET_EEPROM_DELAY);
+
+  // disable strong pullup
+  m_OW_master.OWLevel(OneWireMaster::LEVEL_NORMAL);
+
+  // read the CS byte
+  m_OW_master.OWReadByte(cs);
+
+  if (cs == 0xAA)
+    return Success;
+  // else
+  return OperationFailure;
+}
+
+//----------------------------------------------------------------------
+// Write the scratchpad (challenge or secret)
+//
+// 'sn'        - secret number 0 or 1
+// 'data'      - data to write to the scratchpad (32 bytes)
+//
+// Return: true - select complete
+//         false - error during select, device not present
+//
+OneWireSlave::CmdResult DS28E15_22_25::WriteScratchpad(const uint8_t (&data)[scratchpadSize]) const
+{
+   std::uint8_t buf[256];
+   int cnt = 0, offset;
+
+   buf[cnt++] = CMD_SELECT_SECRET;      
+   if ((romId.familyCode() == DS28E25_FAMILY) || (romId.familyCode() == DS28E22_FAMILY))
+      buf[cnt++] = 0x20;
+   else
+      buf[cnt++] = 0x00;  
+   
+   // Send command
+   m_OW_master.OWWriteBlock(&buf[0], 2);
+
+   // Read CRC
+   m_OW_master.OWReadBlock(&buf[cnt], 2);
+   cnt += 2;
+
+   offset = cnt;
+
+   // add the data
+   memcpy(&buf[cnt], data, scratchpadSize);
+   cnt += scratchpadSize;
+
+   // Send the data
+   m_OW_master.OWWriteBlock(data, scratchpadSize);
+
+   // Read CRC
+   m_OW_master.OWReadBlock(&buf[cnt], 2);
+   cnt += 2;
+   
+   // check first CRC16
+   if (OneWireMaster::calculateCRC16(buf, 0, offset) != 0xB001)
+      return CommunicationError;
+
+   // check the second CRC16
+   if (OneWireMaster::calculateCRC16(buf, offset, (cnt - offset)) != 0xB001)
+      return CommunicationError;
+
+   return Success;
+}
+
+//----------------------------------------------------------------------
+// Load first secret operation on the DS28E25/DS28E22/DS28E15.
+//
+// 'sn'        - secret number 0 or 1
+// 'secret'    - secret to load (32 bytes)
+// 'lock'      - option to lock the secret after the load (lock = true)
+//
+// Return: true - load complete
+//         false - error during load, device not present
+//
+OneWireSlave::CmdResult DS28E15_22_25::LoadSecret(bool lock)
+{
+   std::uint8_t buf[256], cs;
+   int cnt = 0;
+
+   buf[cnt++] = CMD_LOAD_LOCK_SECRET;                 
+   buf[cnt++] = (lock) ? 0xE0 : 0x00;  // lock flag 
+
+   // Send command
+   m_OW_master.OWWriteBlock(&buf[0], 2);
+
+   // Read CRC
+   m_OW_master.OWReadBlock(&buf[cnt], 2);
+   cnt += 2;
+
+   // check CRC16
+   if (OneWireMaster::calculateCRC16(buf, 0, cnt) != 0xB001)
+      return CommunicationError;
+
+   // send release and strong pull-up
+   m_OW_master.OWWriteBytePower(0xAA);
+
+   // now wait for the MAC computation.
+   wait_ms(SECRET_EEPROM_DELAY);
+
+   // disable strong pullup
+   m_OW_master.OWLevel(OneWireMaster::LEVEL_NORMAL);
+
+   // read the CS byte
+   m_OW_master.OWReadByte(cs);
+
+   if (cs == 0xAA)
+     return Success;
+   // else
+   return OperationFailure;
+}
+
+//--------------------------------------------------------------------------
+//  Read page and verify CRC. Multiple pages can
+//  be read without re-selecting the device using the continue flag. 
+// 
+//  Parameters
+//     page - page number where the block to write is located (0 to 15)
+//     rdbuf - 32 byte buffer to contain the data to read
+//     contflag - Flag to indicate the write is continued from the last
+//
+//  Returns: true - block read and verified CRC
+//           false - Failed to write block (no presence or invalid CRC16)
+//
+OneWireSlave::CmdResult DS28E15_22_25::readPage(unsigned int page, std::uint8_t (&rdbuf)[pageSize], bool continuing) const	
+{
+   std::uint8_t buf[256];
+   int cnt, offset;
+
+   cnt = 0;
+   offset = 0;
+   
+   // check if not continuing a previous block write
+   if (!continuing)
+   {
+      buf[cnt++] = CMD_READ_MEMORY;                 
+      buf[cnt++] = page;   // address 
+
+      // Send command
+      m_OW_master.OWWriteBlock(&buf[0], 2);
+
+      // Read CRC
+      m_OW_master.OWReadBlock(&buf[cnt], 2);
+      cnt += 2;
+
+      offset = cnt;
+   }
+
+   // read data and CRC16
+   m_OW_master.OWReadBlock(&buf[cnt], (pageSize + 2));
+   cnt+=34;
+
+   // check the first CRC16
+   if (!continuing)
+   {
+      if (OneWireMaster::calculateCRC16(buf, 0, offset) != 0xB001)
+         return CommunicationError;
+   }
+
+   // check the second CRC16
+   if (OneWireMaster::calculateCRC16(buf, offset, (cnt - offset)) != 0xB001)
+      return CommunicationError;
+
+   // copy the data to the read buffer
+   memcpy(rdbuf, &buf[offset], pageSize);
+
+   return Success;
+}
+
+//--------------------------------------------------------------------------
+//  Write a 4 byte memory block using an authenticated write (with MAC). 
+//  The MAC must be pre-calculated. 
+// 
+//  Parameters
+//     page - page number where the block to write is located (0 to 15)
+//     block - block number in page (0 to 7)
+//     new_data - 4 byte buffer containing the data to write
+//     mac - mac to use for the write
+//     contflag - Flag to indicate the write is continued from the last
+//
+//  Returns: true - block written
+//           false - Failed to write block (no presence or invalid CRC16)
+//
+OneWireSlave::CmdResult DS28E15_22_25::writeAuthSegmentMAC(unsigned int pageNum, unsigned int segmentNum, const std::uint8_t (&newData)[segmentSize], const std::uint8_t (&mac)[macLen], bool continuing)	
+{
+   std::uint8_t buf[256], cs;
+   int cnt, i, offset;
+
+   cnt = 0;
+   offset = 0;
+   
+   // check if not continuing a previous block write
+   if (!continuing)
+   {
+      buf[cnt++] = CMD_WRITE_AUTH_MEMORY;                 
+      buf[cnt++] = (segmentNum << 5) | pageNum;   // address 
+
+      // Send command
+      m_OW_master.OWWriteBlock(&buf[0], 2);
+
+      // Read CRC
+      m_OW_master.OWReadBlock(&buf[cnt], 2);
+      cnt += 2;
+
+      offset = cnt;
+   }
+
+   // add the data
+   for (i = 0; i < 4; i++)
+      buf[cnt++] = newData[i];
+
+   // Send data
+   m_OW_master.OWWriteBlock(newData, segmentSize);
+
+   // read first CRC byte
+   m_OW_master.OWReadByte(buf[cnt++]);
+
+   // read the last CRC and enable power
+   m_OW_master.OWReadBytePower(buf[cnt++]);
+
+      // now wait for the MAC computation.
+   wait_ms(SHA_COMPUTATION_DELAY);
+
+   // disable strong pullup
+   m_OW_master.OWLevel(OneWireMaster::LEVEL_NORMAL);
+
+   // check the first CRC16
+   if (!continuing)
+   {
+      if (OneWireMaster::calculateCRC16(buf, 0, offset) != 0xB001)
+         return CommunicationError;
+   }
+
+   // check the second CRC16
+   unsigned short CRC16 = 0;
+
+   // DS28E25/DS28E22, crc gets calculagted with CS byte 
+   if ((romId.familyCode() == DS28E25_FAMILY) || (romId.familyCode() == DS28E22_FAMILY))
+   {
+      if (continuing)
+         CRC16 = OneWireMaster::calculateCRC16(CRC16, 0xAA);
+   }
+
+   CRC16 = OneWireMaster::calculateCRC16(buf, offset, (cnt - offset), CRC16);
+
+   if (CRC16 != 0xB001)
+      return CommunicationError;
+
+   // transmit MAC as a block
+   m_OW_master.OWWriteBlock(mac, macLen);
+
+   // calculate CRC on MAC
+   CRC16 = OneWireMaster::calculateCRC16(mac, 0, macLen);
+
+   // append read of CRC16 and CS byte
+   m_OW_master.OWReadBlock(&buf[0], 3);
+   cnt = 3;
+
+   // ckeck CRC16
+   CRC16 = OneWireMaster::calculateCRC16(buf, 0, (cnt - 1), CRC16);
+
+   if (CRC16 != 0xB001)
+      return CommunicationError;
+
+   // check CS
+   if (buf[cnt-1] != 0xAA)
+      return OperationFailure;
+
+   // send release and strong pull-up
+   m_OW_master.OWWriteBytePower(0xAA);
+
+   // now wait for the MAC computation.
+   wait_ms(EEPROM_WRITE_DELAY);
+
+   // disable strong pullup
+   m_OW_master.OWLevel(OneWireMaster::LEVEL_NORMAL);
+
+   // read the CS byte
+   m_OW_master.OWReadByte(cs);
+
+   if (cs == 0xAA)
+     return Success;
+   // else
+   return OperationFailure;
+}
+
+//--------------------------------------------------------------------------
+//  Compute MAC to write a 4 byte memory block using an authenticated 
+//  write.
+// 
+//  Parameters
+//     page - page number where the block to write is located (0 to 15)
+//     block - block number in page (0 to 7)
+//     new_data - 4 byte buffer containing the data to write
+//     old_data - 4 byte buffer containing the data to write
+//     manid - 2 byte buffer containing the manufacturer ID (general device: 00h,00h)
+//     mac - buffer to put the calculated mac into
+//
+//  Returns: true - mac calculated
+//           false - Failed to calculate
+//
+ISha256MacCoprocessor::CmdResult DS28E15_22_25::CalculateSegmentWriteMAC256(const ISha256MacCoprocessor & MacCoproc, unsigned int pageNum, unsigned int segmentNum, const std::uint8_t (&newData)[segmentSize], const std::uint8_t (&oldData)[segmentSize], const RomId & romId, const std::uint8_t (&manId)[manIdLen], std::uint8_t (&mac)[macLen])	
+{
+  std::uint8_t MT[ISha256MacCoprocessor::WriteMAC_data_len];
+
+  // insert ROM number
+  memcpy(&MT[0], romId, RomId::byteLen);
+
+  MT[11] = segmentNum;
+  MT[10] = pageNum;
+  MT[9] = manId[0];
+  MT[8] = manId[1];
+
+  // insert old data
+  memcpy(&MT[12], oldData, segmentSize);
+
+  // insert new data
+  memcpy(&MT[16], newData, segmentSize);
+  
+  return MacCoproc.ComputeAndRead_WriteMAC(MT, mac);
+}
+
+
+
+
+ISha256MacCoprocessor::CmdResult DS28E15_22_25::CalculateProtectionWriteMAC256(const ISha256MacCoprocessor & MacCoproc, std::uint8_t newProtection, std::uint8_t oldProtection, const RomId & romId, const std::uint8_t (&manId)[manIdLen], std::uint8_t (&mac)[macLen])
+{
+   std::uint8_t MT[ISha256MacCoprocessor::WriteMAC_data_len];
+  
+   // insert ROM number
+   std::memcpy(MT, romId, RomId::byteLen);
+
+   // instert block and page
+   MT[11] = 0;
+   MT[10] = newProtection & 0x0F;
+
+   MT[9] = manId[0];
+   MT[8] = manId[1];
+
+   // old data
+   MT[12] = (oldProtection & PROT_BIT_AUTHWRITE) ? 0x01 : 0x00;  
+   MT[13] = (oldProtection & PROT_BIT_EPROM) ? 0x01 : 0x00;
+   MT[14] = (oldProtection & PROT_BIT_WRITE) ? 0x01 : 0x00;
+   MT[15] = (oldProtection & PROT_BIT_READ) ? 0x01 : 0x00;
+   // new data
+   MT[16] = (newProtection & PROT_BIT_AUTHWRITE) ? 0x01 : 0x00;  
+   MT[17] = (newProtection & PROT_BIT_EPROM) ? 0x01 : 0x00;
+   MT[18] = (newProtection & PROT_BIT_WRITE) ? 0x01 : 0x00;
+   MT[19] = (newProtection & PROT_BIT_READ) ? 0x01 : 0x00;
+
+   // compute the mac
+   return MacCoproc.ComputeAndRead_WriteMAC(MT, mac);
+}
+
+//--------------------------------------------------------------------------
+//  Write a 4 byte memory block using an authenticated write (with MAC). 
+//  The block location is selected by the 
+//  page number and offset block within the page. Multiple blocks can
+//  be programmed without re-selecting the device using the continue flag. 
+//  This function does not use the Authenticated Write operation. 
+// 
+//  Parameters
+//     page - page number where the block to write is located (0 to 15)
+//     block - block number in page (0 to 7)
+//     new_data - 4 byte buffer containing the data to write
+//     old_data - 4 byte buffer containing the data to write
+//     manid - 2 byte buffer containing the manufacturer ID (general device: 00h,00h)
+//     contflag - Flag to indicate the write is continued from the last
+//
+//  Returns: true - block written
+//           false - Failed to write block (no presence or invalid CRC16)
+//
+OneWireSlave::CmdResult DS28E15_22_25::writeAuthSegment(const ISha256MacCoprocessor & MacCoproc, unsigned int pageNum, unsigned int segmentNum, const std::uint8_t (&newData)[segmentSize], const std::uint8_t (&oldData)[segmentSize], bool continuing)
+{
+  std::uint8_t buf[256], cs;
+  int cnt, offset;
+
+   cnt = 0;
+   offset = 0;
+   
+   // check if not continuing a previous block write
+   if (!continuing)
+   {
+      buf[cnt++] = CMD_WRITE_AUTH_MEMORY;                 
+      buf[cnt++] = (segmentNum << 5) | pageNum;   // address 
+
+      // Send command
+      m_OW_master.OWWriteBlock(&buf[0], 2);
+
+      // Read CRC
+      m_OW_master.OWReadBlock(&buf[cnt], 2);
+      cnt += 2;
+
+      offset = cnt;
+   }
+
+   // add the data
+   for (size_t i = 0; i < segmentSize; i++)
+      buf[cnt++] = newData[i];
+
+   // Send data
+   m_OW_master.OWWriteBlock(newData, segmentSize);
+
+   // read first CRC byte
+   m_OW_master.OWReadByte(buf[cnt++]);
+
+   // read the last CRC and enable power
+   m_OW_master.OWReadBytePower(buf[cnt++]);
+
+   // now wait for the MAC computation.
+   wait_ms(SHA_COMPUTATION_DELAY);
+
+   // disable strong pullup
+   m_OW_master.OWLevel(OneWireMaster::LEVEL_NORMAL);
+
+   // check the first CRC16
+   if (!continuing)
+   {
+      if (OneWireMaster::calculateCRC16(buf, 0, offset) != 0xB001)
+         return CommunicationError;
+   }
+
+   // check the second CRC16
+   unsigned short CRC16 = 0;
+
+   // DS28E25/DS28E22, crc gets calculagted with CS byte
+   if ((romId.familyCode() == DS28E25_FAMILY) || (romId.familyCode() == DS28E22_FAMILY))
+   {
+      if (continuing)
+         CRC16 = OneWireMaster::calculateCRC16(CRC16, 0xAA);
+   }
+   
+   CRC16 = OneWireMaster::calculateCRC16(buf, offset, (cnt - offset), CRC16);
+
+   if (CRC16 != 0xB001)
+      return CommunicationError;
+
+    // compute the mac
+   ISha256MacCoprocessor::CmdResult result;
+   result = CalculateSegmentWriteMAC256(MacCoproc, pageNum, segmentNum, newData, oldData, romId, manId, reinterpret_cast<std::uint8_t (&)[macLen]>(buf));
+   if (result != ISha256MacCoprocessor::Success)
+      return OperationFailure;
+
+   // transmit MAC as a block
+   cnt = 0;
+   m_OW_master.OWWriteBlock(buf, macLen);
+
+   // calculate CRC on MAC
+   CRC16 = OneWireMaster::calculateCRC16(buf, 0, macLen);
+
+   // append read of CRC16 and CS byte
+   m_OW_master.OWReadBlock(&buf[0], 3);
+   cnt = 3;
+
+   // ckeck CRC16
+   CRC16 = OneWireMaster::calculateCRC16(buf, 0, (cnt - 1), CRC16);
+
+   if (CRC16 != 0xB001)
+      return CommunicationError;
+
+   // check CS
+   if (buf[cnt-1] != 0xAA)
+      return OperationFailure;
+
+   // send release and strong pull-up
+   m_OW_master.OWWriteBytePower(0xAA);
+
+   // now wait for the MAC computation.
+   wait_ms(EEPROM_WRITE_DELAY);
+
+   // disable strong pullup
+   m_OW_master.OWLevel(OneWireMaster::LEVEL_NORMAL);
+
+   // read the CS byte
+   m_OW_master.OWReadByte(cs);
+
+   if (cs == 0xAA)
+     return Success;
+   // else
+   return OperationFailure;
+}
+
+
+
+
+OneWireSlave::CmdResult DS28E15_22_25::readSegment(unsigned int page, unsigned int segment, std::uint8_t (&data)[segmentSize]) const
+{
+  OneWireMaster::CmdResult result;
+  std::uint8_t buf[2];
+  
+  buf[0] = CMD_READ_MEMORY;
+  buf[1] = (segment << 5) | page;
+  
+  // Transmit command
+  m_OW_master.OWWriteBlock(buf, 2);
+  
+  // Receive CRC
+  result = m_OW_master.OWReadBlock(buf, 2);
+  
+  // Receive data
+  if (result == OneWireMaster::Success)
+    result = m_OW_master.OWReadBlock(data, segmentSize);
+  
+  return (result == OneWireMaster::Success ? OneWireSlave::Success : OneWireSlave::CommunicationError);
+}
+
+//--------------------------------------------------------------------------
+//  Write a 4 byte memory block. The block location is selected by the 
+//  page number and offset blcok within the page. Multiple blocks can
+//  be programmed without re-selecting the device using the continue flag. 
+//  This function does not use the Authenticated Write operation. 
+// 
+//  Parameters
+//     page - page number where the block to write is located (0 to 15)
+//     block - block number in page (0 to 7)
+//     data - 4 byte buffer containing the data to write
+//     contflag - Flag to indicate the write is continued from the last
+//
+//  Returns: true - block written
+//           false - Failed to write block (no presence or invalid CRC16)
+//
+OneWireSlave::CmdResult DS28E15_22_25::writeSegment(unsigned int page, unsigned int block, const std::uint8_t (&data)[segmentSize], bool continuing)	
+{
+   std::uint8_t buf[256], cs;
+   int cnt, offset;
+
+   cnt = 0;
+   offset = 0;
+   
+   // check if not continuing a previous block write
+   if (!continuing)
+   {
+      buf[cnt++] = CMD_WRITE_MEMORY;                 
+      buf[cnt++] = (block << 5) | page;   // address 
+
+      // Send command 
+      m_OW_master.OWWriteBlock(&buf[0], 2);
+
+      // Read CRC
+      m_OW_master.OWReadBlock(&buf[cnt], 2);
+      cnt += 2;
+
+      offset = cnt;
+   }
+
+   // add the data
+   for (size_t i = 0; i < segmentSize; i++)
+      buf[cnt++] = data[i];
+
+   // Send data
+   m_OW_master.OWWriteBlock(data, segmentSize);
+
+   // Read CRC
+   m_OW_master.OWReadBlock(&buf[cnt], 2);
+   cnt += 2;
+   
+   // check the first CRC16
+   if (!continuing)
+   {
+      if (OneWireMaster::calculateCRC16(buf, 0, offset) != 0xB001)
+         return CommunicationError;
+   }
+
+   // check the second CRC16
+   if (OneWireMaster::calculateCRC16(buf, offset, (cnt - offset)) != 0xB001)
+      return CommunicationError;
+
+   // send release and strong pull-up
+   m_OW_master.OWWriteBytePower(0xAA);
+
+   // now wait for the MAC computation.
+   wait_ms(EEPROM_WRITE_DELAY);
+
+   // disable strong pullup
+   m_OW_master.OWLevel(OneWireMaster::LEVEL_NORMAL);
+
+   // read the CS byte
+   m_OW_master.OWReadByte(cs);
+
+   if (cs == 0xAA)
+     return Success;
+   // else
+   return OperationFailure;
+}
+
+//----------------------------------------------------------------------
+// Performs a Compute Next SHA-256 calculation given the provided 32-bytes
+// of binding data and 8 byte partial secret. The first 8 bytes of the
+// resulting MAC is set as the new secret.
+// 
+// 'binding'  - 32 byte buffer containing the binding data
+// 'partial'  - 8 byte buffer with new partial secret
+// 'page_num'  - page number that the compute is calculated on
+// 'manid'  - manufacturer ID
+//
+// Globals used : SECRET used in calculation and set to new secret
+//
+// Returns: true if compute successful
+//          false failed to do compute
+//
+ISha256MacCoprocessor::CmdResult DS28E15_22_25::CalculateNextSecret(ISha256MacCoprocessor & MacCoproc, const std::uint8_t (&binding)[pageSize], const std::uint8_t (&partial)[scratchpadSize], const RomId & romId, const std::uint8_t (&manId)[manIdLen], unsigned int pageNum)
+{
+  std::uint8_t devicePage[pageSize], deviceScratchpad[scratchpadSize], SSecret_data[ISha256MacCoprocessor::SSecret_data_len];
+
+   // insert page data
+   memcpy(devicePage, binding, pageSize);
+
+   // insert challenge
+   memcpy(deviceScratchpad, partial, scratchpadSize);
+
+   // insert ROM number
+   std::memcpy(SSecret_data, romId, RomId::byteLen);
+
+   SSecret_data[11] = 0x00;
+   SSecret_data[10] = pageNum;
+   SSecret_data[9] = manId[0];
+   SSecret_data[8] = manId[1];
+
+   return MacCoproc.Compute_SSecret(devicePage, deviceScratchpad, SSecret_data);
+}