Implementation of 1-Wire with added Alarm Search Functionality

Dependents:   Max32630_One_Wire_Interface

Revision:
69:f915c4c59a69
Parent:
32:bce180b544ed
Child:
71:562f5c702094
diff -r 5083a49163af -r f915c4c59a69 OneWire_Masters/DS248x/ds248x.cpp
--- a/OneWire_Masters/DS248x/ds248x.cpp	Fri Apr 22 10:36:53 2016 -0500
+++ b/OneWire_Masters/DS248x/ds248x.cpp	Mon May 09 08:29:49 2016 -0500
@@ -35,6 +35,51 @@
 #include "RomId.hpp"
 
 
+enum DS248X_STATUS_BITS
+{
+    STATUS_1WB  = 0x01,
+    STATUS_PPD = 0x02,
+    STATUS_SD = 0x04,
+    STATUS_LL = 0x08,
+    STATUS_RST = 0x10,
+    STATUS_SBR = 0x20,
+    STATUS_TSB = 0x40,
+    STATUS_DIR = 0x80
+};
+
+static const int I2C_WRITE_OK = 0;
+static const int I2C_READ_OK = 0;
+
+
+std::uint8_t Ds248x::Config::readByte() const
+{
+  std::uint8_t config = 0;
+  if (c1WS())
+    config |= 0x08;
+  if (cSPU())
+    config |= 0x04;
+  if (cPDN())
+    config |= 0x02;
+  if (cAPU())
+    config |= 0x01;
+  return config;
+}
+
+std::uint8_t Ds248x::Config::writeByte() const
+{
+  std::uint8_t config = readByte();
+  return ((~config << 4) | config);
+}
+
+void Ds248x::Config::reset()
+{
+  setC1WS(false);
+  setCSPU(false);
+  setCPDN(false);
+  setCAPU(true);
+}
+
+
 //*********************************************************************
 Ds248x::Ds248x(I2C &i2c_bus, DS248X_I2C_ADRS adrs)
 :_p_i2c_bus(&i2c_bus), _i2c_owner(false)
@@ -64,118 +109,54 @@
 //*********************************************************************
 OneWireMaster::CmdResult Ds248x::OWInitMaster(void)
 {
-    return(detect());
-}
-
+    OneWireMaster::CmdResult result;
 
-//*********************************************************************
-OneWireMaster::CmdResult Ds248x::detect(void)
-{
-    OneWireMaster::CmdResult result;
-    
-    // reset the ds2484 ON selected address
+    // reset DS2465 
     result = reset();
-    if(result == OneWireMaster::Success)
-    {
-        // default configuration
-        _c1WS = 0;
-        _cSPU = 0;
-        _cPDN = 0;
-        _cAPU = 0;
-        
-        result = write_config(_c1WS | _cSPU | _cPDN | _cAPU);
-    }
-    
+    if (result != OneWireMaster::Success)
+    return result;
+
+    // write the default configuration setup
+    Config defaultConfig;
+    result = writeConfig(defaultConfig, true);
     return result;
 }
 
 
 //*********************************************************************
 OneWireMaster::CmdResult Ds248x::reset(void)
-{
-    OneWireMaster::CmdResult result;
-    
-    char status;
-    char packet[] = {CMD_DRST};
-    
+{    
     // Device Reset
     //   S AD,0 [A] DRST [A] Sr AD,1 [A] [SS] A\ P
     //  [] indicates from slave
     //  SS status byte to read to verify state
     
-    if(_p_i2c_bus->write(_w_adrs, packet, 1) != I2C_WRITE_OK)
-    {
-        result = OneWireMaster::CommunicationWriteError;
-    }
-    else
-    {
-        if(_p_i2c_bus->read(_r_adrs, &status, 1) != I2C_READ_OK)
-        {
-            result = OneWireMaster::CommunicationReadError;
-        }
-        else
-        {
-            if((status & 0xF7) == 0x10)
-            {
-                result = OneWireMaster::Success;
-            }
-            else
-            {
-                result = OneWireMaster::OperationFailure;
-            }
-        }
-    }
-    
-    return result;   
+  OneWireMaster::CmdResult result;
+  std::uint8_t buf;
+  
+  result = sendCommand(CMD_DRST);
+  
+  if (result == OneWireMaster::Success)
+    result = readRegister(REG_STATUS, buf, true);
+
+  if (result == OneWireMaster::Success)
+  {
+    if ((buf & 0xF7) != 0x10)
+      result = OneWireMaster::OperationFailure;
+  }
+   
+  if (result == OneWireMaster::Success)
+    OWReset(); // do a command to get 1-Wire master reset out of holding state
+
+  return result; 
 }
 
 
 //*********************************************************************
-OneWireMaster::CmdResult Ds248x::write_config(uint8_t config)
+OneWireMaster::CmdResult Ds248x::channelSelect(uint8_t channel)
 {
     OneWireMaster::CmdResult result;
-    
-    char read_config;
-    char packet [] = {CMD_WCFG, (config | (~config << 4))};
-    
-    if(_p_i2c_bus->write(_w_adrs, packet, 2) != I2C_WRITE_OK)
-    {
-        result = OneWireMaster::CommunicationWriteError;
-    }
-    else
-    {
-        if(_p_i2c_bus->read(_r_adrs, &read_config, 1) != I2C_READ_OK)
-        {
-            result = OneWireMaster::CommunicationReadError;
-        }
-        else
-        {
-            // check for failure due to incorrect read back
-            if (config != read_config)
-            {
-                reset();
-                result = OneWireMaster::OperationFailure;
-            }
-            else
-            {
-                result = OneWireMaster::Success;
-            }
-        }
-    }
-    
-    return result;   
-}
-
-
-//*********************************************************************
-OneWireMaster::CmdResult Ds248x::channel_select(uint8_t channel)
-{
-    OneWireMaster::CmdResult result;
-    
-    char ch, ch_read, check;
-    char packet [2];
-    
-    packet[0] = CMD_CHSL;
+    uint8_t ch, ch_read;
     
     // Channel Select (Case A)
     //   S AD,0 [A] CHSL [A] CC [A] Sr AD,1 [A] [RR] A\ P
@@ -195,202 +176,14 @@
       case 7: ch = 0x87; ch_read = 0x87; break;
     };
     
-    packet[1] = ch;
-    
-    if(_p_i2c_bus->write(_w_adrs, packet, 2) != I2C_WRITE_OK)
+    result = sendCommand(CMD_CHSL, ch);
+    if (result == OneWireMaster::Success)
     {
-        result = OneWireMaster::CommunicationWriteError;
-    }
-    else
-    {
-        if(_p_i2c_bus->read(_r_adrs, &check, 1) != I2C_READ_OK)
-        {
-            result = OneWireMaster::CommunicationReadError;
-        }
-        else
+        result = readRegister(REG_CHANNEL_SELECT, ch, true);
+        if (result == OneWireMaster::Success)
         {
             // check for failure due to incorrect read back of channel
-            if (check == ch_read)
-            {
-                result = OneWireMaster::Success;
-            }
-            else
-            {
-                result = OneWireMaster::OperationFailure;
-            }
-        }
-    }
-    
-    return result;
-}
-
-
-//*********************************************************************
-OneWireMaster::CmdResult Ds248x::adjust_timing(uint8_t param, uint8_t val)
-{
-    OneWireMaster::CmdResult result;
-    
-    char read_port_config;
-    char control_byte;
-
-    control_byte = (((param & 0x0F) << 4) | (val & 0x0F));
-
-    char packet [] = {CMD_A1WP, control_byte};
-
-    if(_p_i2c_bus->write(_w_adrs, packet, 2) != I2C_WRITE_OK)
-    {
-        result = OneWireMaster::CommunicationWriteError;
-    }
-    else
-    {
-        if(_p_i2c_bus->read(_r_adrs, &read_port_config, 1) != I2C_READ_OK)
-        {
-            result = OneWireMaster::CommunicationReadError;
-        }
-        else
-        {
-            // check for failure due to incorrect read back
-            if ((control_byte & 0x0F) != read_port_config) 
-            {
-                result = OneWireMaster::OperationFailure;
-                reset();
-            }
-            else
-            {
-                result = OneWireMaster::Success;
-            }
-        }
-    }
-    
-    return result;
-}
-
-
-//*********************************************************************
-OneWireMaster::CmdResult Ds248x::OWTriplet(SearchDirection & search_direction, std::uint8_t & sbr, std::uint8_t & tsb)
-{
-    OneWireMaster::CmdResult result;
-    
-    uint8_t poll_count = 0;
-    char packet [] = {CMD_1WT, search_direction ? 0x80 : 0x00};
-    char read_data;
-
-    // 1-Wire Triplet (Case B)
-    //   S AD,0 [A] 1WT [A] SS [A] Sr AD,1 [A] [Status] A [Status] A\ P
-    //                                         \--------/
-    //                           Repeat until 1WB bit has changed to 0
-    //  [] indicates from slave
-    //  SS indicates byte containing search direction bit value in msbit
-
-    if(_p_i2c_bus->write(_w_adrs, packet, 2) != I2C_WRITE_OK)
-    {
-        result = OneWireMaster::CommunicationWriteError;
-    }
-    else
-    {
-        // loop checking 1WB bit for completion of 1-Wire operation
-        // abort if poll limit reached
-        
-        //dummy write for loop 
-        result = OneWireMaster::Success; //so far
-        do 
-        {
-            if(_p_i2c_bus->read(_r_adrs, &read_data, 1) != I2C_READ_OK)
-            {
-                result = OneWireMaster::CommunicationReadError;
-            }
-        } 
-        while ((read_data & STATUS_1WB) && (poll_count++ < POLL_LIMIT) && (result != OneWireMaster::CommunicationReadError));
-        
-        if((result == OneWireMaster::CommunicationReadError) || (poll_count >= POLL_LIMIT))
-        {
-            // check for failure due to poll limit reached
-            if(poll_count >= POLL_LIMIT)  
-            {
-                // handle error
-                // ...
-                reset();
-                result = OneWireMaster::TimeoutError;
-            }
-        }
-        else
-        {
-            // check bit results in status byte
-            sbr = ((read_data & STATUS_SBR) == STATUS_SBR);
-            tsb = ((read_data & STATUS_TSB) == STATUS_TSB);
-            search_direction = ((read_data & STATUS_DIR) == STATUS_DIR) ? DIRECTION_WRITE_ONE : DIRECTION_WRITE_ZERO;
-            
-            result = OneWireMaster::Success;
-        }
-    }
-
-    return result;
-}
-
-
-//*********************************************************************
-OneWireMaster::CmdResult Ds248x::OWReset(void)
-{
-    OneWireMaster::CmdResult result;
-    
-    uint8_t poll_count = 0;
-    char status;
-    char packet [] = {CMD_1WRS};
-
-    // 1-Wire reset (Case B)
-    //   S AD,0 [A] 1WRS [A] Sr AD,1 [A] [Status] A [Status] A\ P
-    //                                   \--------/
-    //                       Repeat until 1WB bit has changed to 0
-    //  [] indicates from slave
-
-    if(_p_i2c_bus->write(_w_adrs, packet, 1) != I2C_WRITE_OK)
-    {
-        result = OneWireMaster::CommunicationWriteError;
-    }
-    else
-    {
-        // loop checking 1WB bit for completion of 1-Wire operation
-        // abort if poll limit reached
-        //dummy write for loop 
-        result = OneWireMaster::Success; //so far
-        do 
-        {
-            if(_p_i2c_bus->read(_r_adrs, &status, 1) != I2C_READ_OK)
-            {
-                result = OneWireMaster::CommunicationReadError;
-            }
-        } 
-        while ((status & STATUS_1WB) && (poll_count++ < POLL_LIMIT) && (result != OneWireMaster::CommunicationReadError));
-        
-        if((result == OneWireMaster::CommunicationReadError) || (poll_count >= POLL_LIMIT))
-        {
-            // check for failure due to poll limit reached
-            if(poll_count >= POLL_LIMIT)  
-            {
-                // handle error
-                // ...
-                reset();
-                result = OneWireMaster::TimeoutError;
-            }
-        }
-        else
-        {
-            // check for short condition
-            if (status & STATUS_SD)
-            {
-                _short_detected = true;
-            }
-            else
-            {
-                _short_detected = false;
-            }
-        
-            // check for presence detect
-            if (status & STATUS_PPD)
-            {
-                result = OneWireMaster::Success;
-            }
-            else
+            if (ch != ch_read)
             {
                 result = OneWireMaster::OperationFailure;
             }
@@ -402,18 +195,89 @@
 
 
 //*********************************************************************
-OneWireMaster::CmdResult Ds248x::OWTouchBit(uint8_t & sendrecvbit, OWLevel after_level)
+OneWireMaster::CmdResult Ds248x::adjustTiming(DS2484_ADJST_PARAMS param, uint8_t val)
 {
     OneWireMaster::CmdResult result;
     
-    result = ConfigureSPU(after_level == LEVEL_STRONG);
-    if (result != OneWireMaster::Success)
+    uint8_t read_port_config;
+    uint8_t control_byte;
+
+    control_byte = (((param & 0x0F) << 4) | (val & 0x0F));
+    
+    result = sendCommand(CMD_A1WP, control_byte);
+    if (result != Success)
         return result;
+        
+    result = readRegister(REG_PORT_CONFIG, read_port_config, true);
+    if (result != Success)
+        return result;
+        
+    if ((control_byte & 0x0F) != read_port_config) 
+        result = OneWireMaster::OperationFailure;
     
-    uint8_t poll_count = 0;
-    char status;
-    char packet[] = {CMD_1WSB, sendrecvbit ? 0x80 : 0x00};
+    return result;
+}
+
+
+//*********************************************************************
+OneWireMaster::CmdResult Ds248x::OWTriplet(SearchDirection & search_direction, std::uint8_t & sbr, std::uint8_t & tsb)
+{
+    // 1-Wire Triplet (Case B)
+    //   S AD,0 [A] 1WT [A] SS [A] Sr AD,1 [A] [Status] A [Status] A\ P
+    //                                         \--------/
+    //                           Repeat until 1WB bit has changed to 0
+    //  [] indicates from slave
+    //  SS indicates byte containing search direction bit value in msbit
+
+  OneWireMaster::CmdResult result;
+  result = sendCommand(CMD_1WT, (std::uint8_t)((search_direction == DIRECTION_WRITE_ONE) ? 0x80 : 0x00));
+  if (result == OneWireMaster::Success)
+  {
+    std::uint8_t status;
+    result = pollBusy(&status);
+    if (result == OneWireMaster::Success)
+    {
+      // check bit results in status byte
+      sbr = ((status & STATUS_SBR) == STATUS_SBR);
+      tsb = ((status & STATUS_TSB) == STATUS_TSB);
+      search_direction = ((status & STATUS_DIR) == STATUS_DIR) ? DIRECTION_WRITE_ONE : DIRECTION_WRITE_ZERO;
+    }
+  }
+  return result;
+}
+
 
+//*********************************************************************
+OneWireMaster::CmdResult Ds248x::OWReset(void)
+{
+    // 1-Wire reset (Case B)
+    //   S AD,0 [A] 1WRS [A] Sr AD,1 [A] [Status] A [Status] A\ P
+    //                                   \--------/
+    //                       Repeat until 1WB bit has changed to 0
+    //  [] indicates from slave
+
+  OneWireMaster::CmdResult result;
+  std::uint8_t buf;
+    
+  result = sendCommand(CMD_1WRS);
+
+  if (result == OneWireMaster::Success)
+    result = pollBusy(&buf);
+  
+  if (result == OneWireMaster::Success)
+  {       
+    // check for presence detect
+    if ((buf & STATUS_PPD) != STATUS_PPD)
+      result = OneWireMaster::OperationFailure;
+  }
+
+  return result;
+}
+
+
+//*********************************************************************
+OneWireMaster::CmdResult Ds248x::OWTouchBit(uint8_t & sendrecvbit, OWLevel after_level)
+{
     // 1-Wire bit (Case B)
     //   S AD,0 [A] 1WSB [A] BB [A] Sr AD,1 [A] [Status] A [Status] A\ P
     //                                          \--------/
@@ -421,69 +285,29 @@
     //  [] indicates from slave
     //  BB indicates byte containing bit value in msbit
 
-    if(_p_i2c_bus->write(_w_adrs, packet, 2) != I2C_WRITE_OK)
-    {
-        result = OneWireMaster::CommunicationWriteError;
-    }
-    else
-    {
-        // loop checking 1WB bit for completion of 1-Wire operation
-        // abort if poll limit reached
-        //dummy write for loop 
-        result = OneWireMaster::Success; //so far
-        do 
-        {
-            if(_p_i2c_bus->read(_r_adrs, &status, 1) != I2C_READ_OK)
-            {
-                result = OneWireMaster::CommunicationReadError;
-            }
-        } 
-        while ((status & STATUS_1WB) && (poll_count++ < POLL_LIMIT) && (result != OneWireMaster::CommunicationReadError));
-        
-        if((result == OneWireMaster::CommunicationReadError) || (poll_count >= POLL_LIMIT))
-        {
-            // check for failure due to poll limit reached
-            if (poll_count >= POLL_LIMIT) 
-            {
-                // handle error
-                // ...
-                reset();
-                result = OneWireMaster::TimeoutError;
-            }
-        }
-        else
-        {
-            // return bit state through out param
-            if (status & STATUS_SBR)
-            {
-                sendrecvbit = 1;
-                
-            }
-            else
-            {
-                sendrecvbit = 0;
-            }
-            result = OneWireMaster::Success;
-        }
-    }
-
-    return result; 
+  OneWireMaster::CmdResult result;
+  
+  result = configureLevel(after_level);
+  if (result != OneWireMaster::Success)
+    return result;
+  
+  std::uint8_t status;
+  
+  result = sendCommand(CMD_1WSB, (std::uint8_t)(sendrecvbit ? 0x80 : 0x00));
+  
+  if (result == OneWireMaster::Success)
+    result = pollBusy(&status);
+ 
+  if (result == OneWireMaster::Success)
+    sendrecvbit = (status & STATUS_SBR);
+  
+  return result;
 }
 
 
 //*********************************************************************
 OneWireMaster::CmdResult Ds248x::OWWriteByte(uint8_t sendbyte, OWLevel after_level)
 {
-    OneWireMaster::CmdResult result;
-    
-    result = ConfigureSPU(after_level == LEVEL_STRONG);
-    if (result != OneWireMaster::Success)
-        return result;
-    
-    uint8_t poll_count = 0;
-    char status;
-    char packet [] = {CMD_1WWB, sendbyte};
-
     // 1-Wire Write Byte (Case B)
     //   S AD,0 [A] 1WWB [A] DD [A] Sr AD,1 [A] [Status] A [Status] A\ P
     //                                          \--------/
@@ -491,136 +315,51 @@
     //  [] indicates from slave
     //  DD data to write
 
-    if(_p_i2c_bus->write(_w_adrs, packet, 2) != I2C_WRITE_OK)
-    {
-        result = OneWireMaster::CommunicationWriteError;
-    }
-    else
-    {
-        // loop checking 1WB bit for completion of 1-Wire operation
-        // abort if poll limit reached
-        //dummy write for loop 
-        result = OneWireMaster::Success; //so far
-        do 
-        {
-            if(_p_i2c_bus->read(_r_adrs, &status, 1) != I2C_READ_OK)
-            {
-                result = OneWireMaster::CommunicationReadError;
-            }
-        } 
-        while ((status & STATUS_1WB) && (poll_count++ < POLL_LIMIT) && (result != OneWireMaster::CommunicationReadError));
-        
-        if((result == OneWireMaster::CommunicationReadError) || (poll_count >= POLL_LIMIT))
-        {
-            // check for failure due to poll limit reached
-            if (poll_count >= POLL_LIMIT) 
-            {
-                // handle error
-                // ...
-                reset();
-                result = OneWireMaster::TimeoutError;
-            }
-        }
-        else
-        {
-            result = OneWireMaster::Success;
-        }
-    }
+  OneWireMaster::CmdResult result;
+  
+  result = configureLevel(after_level);
+  if (result != OneWireMaster::Success)
+    return result;
+  
+  result = sendCommand(CMD_1WWB, sendbyte);
+  if (result == OneWireMaster::Success)
+    result = pollBusy();
 
-    return result;
+  return result;
 }
 
 
 //*********************************************************************
 OneWireMaster::CmdResult Ds248x::OWReadByte(uint8_t & recvbyte, OWLevel after_level)
 {
-    OneWireMaster::CmdResult result;
-    
-    if (after_level == LEVEL_STRONG) // Enabling strong pull-up after a Read Byte command is not supported natively by the DS248x
-    {
-        uint8_t recvbit;
-        recvbyte = 0;
-        
-        for (unsigned int i = 1; i <= 8; i++)
-        {
-            // Set strong pull-up on last bit
-            result = OWReadBit(recvbit, (i == 8 ? LEVEL_STRONG : LEVEL_NORMAL));
-            if (result != Success)
-                break;
-            recvbyte = (recvbyte << 1) | recvbit;
-        }
-    }
-    else
-    {
-        uint8_t poll_count = 0;
-        char data, status;
-        char packet[2] = {CMD_1WRB, 0};
-
-        // 1-Wire Read Bytes (Case C)
-        //   S AD,0 [A] 1WRB [A] Sr AD,1 [A] [Status] A [Status] A\
-        //                                   \--------/
-        //                     Repeat until 1WB bit has changed to 0
-        //   Sr AD,0 [A] SRP [A] E1 [A] Sr AD,1 [A] DD A\ P
-        //
-        //  [] indicates from slave
-        //  DD data read
+    // 1-Wire Read Bytes (Case C)
+    //   S AD,0 [A] 1WRB [A] Sr AD,1 [A] [Status] A [Status] A\
+    //                                   \--------/
+    //                     Repeat until 1WB bit has changed to 0
+    //   Sr AD,0 [A] SRP [A] E1 [A] Sr AD,1 [A] DD A\ P
+    //
+    //  [] indicates from slave
+    //  DD data read
 
-        if(_p_i2c_bus->write(_w_adrs, packet, 1) != I2C_WRITE_OK)
-        {
-            result = OneWireMaster::CommunicationWriteError;
-        }
-        else
-        {
-            // loop checking 1WB bit for completion of 1-Wire operation
-            // abort if poll limit reached
-            //dummy write for loop 
-            result = OneWireMaster::Success; //so far
-            do 
-            {
-                if(_p_i2c_bus->read(_r_adrs, &status, 1) != I2C_READ_OK)
-                {
-                    result = OneWireMaster::CommunicationReadError;
-                }
-            } 
-            while ((status & STATUS_1WB) && (poll_count++ < POLL_LIMIT) && (result != OneWireMaster::CommunicationReadError));
-            
-            if((result == OneWireMaster::CommunicationReadError) || (poll_count >= POLL_LIMIT))
-            {
-                // check for failure due to poll limit reached
-                if (poll_count >= POLL_LIMIT) 
-                {
-                    // handle error
-                    // ...
-                    reset();
-                    result = OneWireMaster::TimeoutError;
-                }
-            }
-            else
-            {
-                packet[0] = CMD_SRP;
-                packet[1] = 0xE1;
-            
-                if(_p_i2c_bus->write(_w_adrs, packet, 2) != I2C_WRITE_OK)
-                {
-                    result = OneWireMaster::CommunicationWriteError;
-                }
-                else
-                {
-                    if(_p_i2c_bus->read(_r_adrs, &data, 1) != I2C_READ_OK)
-                    {
-                        result = OneWireMaster::CommunicationReadError;
-                    }
-                    else
-                    {
-                        recvbyte = data;
-                        result = OneWireMaster::Success;
-                    }
-                }
-            }
-        }
-    }
-    
+  OneWireMaster::CmdResult result;
+  std::uint8_t buf;
+  
+  result = configureLevel(after_level);
+  if (result != OneWireMaster::Success)
     return result;
+   
+  result = sendCommand(CMD_1WRB);
+
+  if (result == OneWireMaster::Success)
+    result = pollBusy();
+
+  if (result == OneWireMaster::Success)
+    result = readRegister(REG_READ_DATA, buf);
+  
+  if (result == OneWireMaster::Success)
+    recvbyte = buf;
+   
+  return result;
 }
 
 
@@ -664,56 +403,26 @@
 //*********************************************************************
 OneWireMaster::CmdResult Ds248x::OWSetSpeed(OWSpeed new_speed)
 {
-    // set the speed
-    if (new_speed == SPEED_OVERDRIVE)
-    {
-        _c1WS = CONFIG_1WS;
-    }
-    else
-    {
-        _c1WS = 0;
-    }
+  // Requested speed is already set
+  if (m_curConfig.c1WS() == (new_speed == SPEED_OVERDRIVE))
+    return OneWireMaster::Success;
+       
+  // set the speed
+  Config newConfig = m_curConfig;
+  newConfig.setC1WS(new_speed == SPEED_OVERDRIVE);
 
-    // write the new config, and return result of op
-    return write_config(_c1WS | _cSPU | _cPDN | _cAPU);
+  // write the new config
+  return writeConfig(newConfig, true);
 }
 
 
 //*********************************************************************
 OneWireMaster::CmdResult Ds248x::OWSetLevel(OWLevel new_level)
 {
-    OneWireMaster::CmdResult result;
-    
-    // function only will turn back to non-strong pull-up
-    if (new_level != LEVEL_NORMAL)
-    {
-        result = OneWireMaster::OperationFailure;
-    }
-    else
-    {
-        // clear the strong pull-up bit in the global config state
-        _cSPU = 0;
-        
-        result = write_config(_c1WS | _cSPU | _cPDN | _cAPU);
-    }
-
-    return result;
-}
-
-
-OneWireMaster::CmdResult Ds248x::ConfigureSPU(bool spu_enable)
-{
-  OneWireMaster::CmdResult result;
-  if ((_cSPU == CONFIG_SPU) != spu_enable)
-  {
-    _cSPU = spu_enable;
-    result =  write_config(_c1WS | _cSPU | _cPDN | _cAPU);
-  }
-  else
-  {
-    result = OneWireMaster::Success;
-  }
-  return result;
+    if (new_level == LEVEL_STRONG)
+        return OneWireMaster::OperationFailure;
+  
+    return configureLevel(new_level);
 }
 
 
@@ -723,3 +432,103 @@
     _w_adrs = (adrs << 1);
     _r_adrs = (_w_adrs | 1);
 }
+
+
+
+
+OneWireMaster::CmdResult Ds248x::writeConfig(const Config & config, bool verify)
+{
+  std::uint8_t configBuf;
+  OneWireMaster::CmdResult result;
+   
+  configBuf = config.writeByte();
+  result = sendCommand(CMD_WCFG, configBuf);
+  if (verify)
+  {
+    if (result == OneWireMaster::Success)
+    {
+      result = readRegister(REG_CONFIG, configBuf);
+    }
+    if (result == OneWireMaster::Success)
+    {
+      if (configBuf != config.readByte())
+        result = OneWireMaster::OperationFailure;
+    }
+  }
+  
+  if (result == OneWireMaster::Success)
+    m_curConfig = config;
+
+  return result;
+}
+
+OneWireMaster::CmdResult Ds248x::readRegister(DS248X_REG reg, std::uint8_t & buf, bool skipSetPointer) const
+{
+    CmdResult result;
+    result = sendCommand(CMD_SRP, reg);
+    if (result == Success)
+    {
+        if (_p_i2c_bus->read(_r_adrs, reinterpret_cast<char *>(&buf), 1) != I2C_READ_OK)
+            result = CommunicationReadError;
+    }
+    return result;
+}
+
+OneWireMaster::CmdResult Ds248x::pollBusy(std::uint8_t * pStatus)
+{
+  const unsigned int pollLimit = 200;
+
+  OneWireMaster::CmdResult result;
+  std::uint8_t status;
+  unsigned int pollCount = 0;
+   
+  do
+  {
+    result = readRegister(REG_STATUS, status, true);
+    if (result != OneWireMaster::Success)
+      return result;
+    if (pStatus != NULL)
+        *pStatus = status;
+    if (pollCount++ >= pollLimit)
+      return OneWireMaster::TimeoutError;
+  } while (status & STATUS_1WB);
+
+  return OneWireMaster::Success;
+}
+
+OneWireMaster::CmdResult Ds248x::configureLevel(OWLevel level)
+{
+    OneWireMaster::CmdResult result;
+    if (m_curConfig.cSPU() != (level == LEVEL_STRONG))
+    {
+        Config newConfig = m_curConfig;
+        newConfig.setCSPU(level == LEVEL_STRONG);
+        result = writeConfig(newConfig, true);
+    }
+    else
+    {
+        result = OneWireMaster::Success;
+    }
+    return result;
+}
+
+OneWireMaster::CmdResult Ds248x::sendCommand(DS248X_CMDS cmd) const
+{
+    CmdResult result;
+    if (_p_i2c_bus->write(_w_adrs, reinterpret_cast<const char *>(&cmd), 1) == I2C_WRITE_OK)
+        result = Success;
+    else
+        result = CommunicationWriteError;
+    return result;
+}
+
+OneWireMaster::CmdResult Ds248x::sendCommand(DS248X_CMDS cmd, std::uint8_t param) const
+{
+    CmdResult result;
+    char buf[2] = { cmd, param };
+    if (_p_i2c_bus->write(_w_adrs, buf, 2) == I2C_WRITE_OK)
+        result = Success;
+    else
+        result = CommunicationWriteError;
+    return result;
+}