diff --git a/.gitignore b/.gitignore
index 27eeea4..1766e34 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@
# #
# Date Author Comments #
# ========== ============================= =========================== #
+# 2010-01-27 https://github.com/SV-Zanshin Ignores for Doxygen #
# 2018-09-22 https://github.com/SV-Zanshin Ignores for MS VS 2017 #
# 2018-06-24 https://github.com/SV-Zanshin Changed file #
# #
@@ -87,3 +88,8 @@ Release
*.vcxproj
*.filters
*.user
+
+########################################################################
+# Files and directories from doxygen #
+########################################################################
+html
diff --git a/src/DSFamily.cpp b/src/DSFamily.cpp
index e271394..938ac2a 100644
--- a/src/DSFamily.cpp
+++ b/src/DSFamily.cpp
@@ -1,608 +1,785 @@
-/*******************************************************************************************************************
-** Class definition for the DSFamily class, see the class header for detailed comments as well as current version **
-** information. This file defines the methods and variables in the class **
-** **
-** This program is free software: you can redistribute it and/or modify it under the terms of the GNU General **
-** Public License as published by the Free Software Foundation, either version 3 of the License, or (at your **
-** option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY **
-** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
-** GNU General Public License for more details. You should have received a copy of the GNU General Public License **
-** along with this program. If not, see . **
-** **
-*******************************************************************************************************************/
-#include "DSFamily.h" // Include the header definition //
+/*! @file DSFamily.cpp
+ @section DSFamilycpp_intro_section Description
+
+Arduino Library class to access the DS Family of 1-wire temperature sensors\n\n
+See main library header file for details
+*/
+#include "DSFamily.h" // Include the header definition
/*******************************************************************************************************************
** Declare constants used in the class, but ones that are not visible as public or private class components **
*******************************************************************************************************************/
-const uint8_t DS18B20_FAMILY = 0x28; // The Family byte for DS18B20 //
-const uint8_t DS18S20_FAMILY = 0x10; // The family byte for DS18S20 //
-const uint8_t DS28EA00_FAMILY = 0x42; // The family byte for DS28EA00 //
-const uint8_t DS1825_FAMILY = 0x3B; // The family byte for DS1825 //
-const uint8_t DS1822_FAMILY = 0x22; // The family byte for DS1822 //
-const uint8_t DS_START_CONVERT = 0x44; // Command to start conversion //
-const uint8_t DS_READ_SCRATCHPAD = 0xBE; // Command to read the temperature //
-const uint8_t DS_READ_POWER_SUPPLY = 0xB4; // Command to read the temperature //
-const uint8_t DS_WRITE_SCRATCHPAD = 0x4E; // Write to the DS scratchpad //
-const uint8_t DS_COPY_SCRATCHPAD = 0x48; // Copy the contents of scratchpad //
-const uint8_t DS_SKIP_ROM = 0xCC; // Skip the ROM address on 1-Wire //
-const uint8_t DS_SELECT_ROM = 0x55; // Select the ROM address on 1-Wire //
-const uint8_t DS_SEARCH = 0xF0; // Search the 1-Wire for devices //
-const int16_t DS_BAD_TEMPERATURE = 0xFC90; // Bad measurement value, -55°C //
-const uint8_t DS_MAX_NV_CYCLE_TIME = 100; // Max ms taken to write NV memory //
-const uint8_t DS_USER_BYTE_1 = 2; // The 2nd scratchpad byte //
-const uint8_t DS_USER_BYTE_2 = 3; // The 3rd scratchpad byte //
-const uint8_t DS_CONFIG_BYTE = 4; // The 4th scratchpad byte //
-const uint16_t DS_12b_CONVERSION_TIME = 750; // Max ms taken to convert @ 12bits //
-const uint16_t DS_11b_CONVERSION_TIME = 375; // Max ms taken to convert @ 11bits //
-const uint16_t DS_10b_CONVERSION_TIME = 188; // Max ms taken to convert @ 10bits //
-const uint16_t DS_9b_CONVERSION_TIME = 94; // Max ms taken to convert @ 9bits //
+const uint8_t DS18B20_FAMILY = 0x28; ///< The Family byte for DS18B20
+const uint8_t DS18S20_FAMILY = 0x10; ///< The family byte for DS18S20
+const uint8_t DS28EA00_FAMILY = 0x42; ///< The family byte for DS28EA00
+const uint8_t DS1825_FAMILY = 0x3B; ///< The family byte for DS1825
+const uint8_t DS1822_FAMILY = 0x22; ///< The family byte for DS1822
+const uint8_t DS_START_CONVERT = 0x44; ///< Command to start conversion
+const uint8_t DS_READ_SCRATCHPAD = 0xBE; ///< Command to read the temperature
+const uint8_t DS_READ_POWER_SUPPLY = 0xB4; ///< Command to read the temperature
+const uint8_t DS_WRITE_SCRATCHPAD = 0x4E; ///< Write to the DS scratchpad
+const uint8_t DS_COPY_SCRATCHPAD = 0x48; ///< Copy the contents of scratchpad
+const uint8_t DS_SKIP_ROM = 0xCC; ///< Skip the ROM address on 1-Wire
+const uint8_t DS_SELECT_ROM = 0x55; ///< Select the ROM address on 1-Wire
+const uint8_t DS_SEARCH = 0xF0; ///< Search the 1-Wire for devices
+const int16_t DS_BAD_TEMPERATURE = 0xFC90; ///< Bad measurement value, -55°C
+const uint8_t DS_MAX_NV_CYCLE_TIME = 100; ///< Max ms taken to write NV memory
+const uint8_t DS_USER_BYTE_1 = 2; ///< The 2nd scratchpad byte
+const uint8_t DS_USER_BYTE_2 = 3; ///< The 3rd scratchpad byte
+const uint8_t DS_CONFIG_BYTE = 4; ///< The 4th scratchpad byte
+const uint16_t DS_12b_CONVERSION_TIME = 750; ///< Max ms taken to convert @ 12bits
+const uint16_t DS_11b_CONVERSION_TIME = 375; ///< Max ms taken to convert @ 11bits
+const uint16_t DS_10b_CONVERSION_TIME = 188; ///< Max ms taken to convert @ 10bits
+const uint16_t DS_9b_CONVERSION_TIME = 94; ///< Max ms taken to convert @ 9bits
-/*******************************************************************************************************************
-** Class Constructor instantiates the class and uses the initializer list to also instantiate the 1-Wire microLAN **
-** on the defined pin and to set the maximum number of thermometers that the system can store in EEPROM. The **
-** latter is dynamic because it depends upon which Atmel processor is being used, as each one has different amount**
-** off EEPROM space available **
-*******************************************************************************************************************/
-DSFamily_Class::DSFamily_Class(const uint8_t OneWirePin, // CONSTRUCTOR - Instantiate 1-Wire //
- const uint8_t ReserveRom) // protocol //
- : ConversionMillis(DS_12b_CONVERSION_TIME), // Default conversion ms to maximum //
- _MaxThermometers((E2END-ReserveRom)/8) { // //
- pinMode(OneWirePin, INPUT); // Make the 1-Wire pin an input //
- bitmask = PIN_TO_BITMASK(OneWirePin); // Set the bitmask //
- baseReg = PIN_TO_BASEREG(OneWirePin); // Set the base register //
- reset_search(); // Reset the search status //
-} // of class constructor //----------------------------------//
+/*!
+* @brief Class constructor
+* @details Class Constructor instantiates the class and uses the initializer list to also instantiate the 1-Wire
+* microLAN on the defined pin and to set the maximum number of thermometers that the system can store in
+* EEPROM. The latter is dynamic because it depends upon which Atmel processor is being used, as each one
+* has different amount of EEPROM space available
+* @param[in] OneWirePin 1-Wire microLAN pin number
+* @param[in] ReserveRom (Optional) Number of bytes of ROM space to reserve, used to calculate _MaxThermometers
+*/
+DSFamily_Class::DSFamily_Class(const uint8_t OneWirePin, const uint8_t ReserveRom)
+ : ConversionMillis(DS_12b_CONVERSION_TIME), _MaxThermometers((E2END-ReserveRom)/8)
+{
+ pinMode(OneWirePin, INPUT); // Make the 1-Wire pin an input
+ bitmask = PIN_TO_BITMASK(OneWirePin); // Set the bitmask
+ baseReg = PIN_TO_BASEREG(OneWirePin); // Set the base register
+ reset_search(); // Reset the search status
+} // of class constructor
-/*******************************************************************************************************************
-** Class Destructor currently does nothing and is included for compatibility purposes **
-*******************************************************************************************************************/
-DSFamily_Class::~DSFamily_Class() { } // unused DESTRUCTOR //
+/*!
+* @brief Class destructor
+* @details Currently empty and unused
+*/
+DSFamily_Class::~DSFamily_Class() {}
-/*******************************************************************************************************************
-** Use the standardized 1-Wire microLAN search mechanism to discover all DS devices. Each device has a unique **
-** 8-byte ROM address, which is stored at the end of program's EEPROM. Since each Atmel chip has a different **
-** amount of memory, and the class constructor allows the user to specify a number of bytes to reserve at the the **
-** beginning of the EEPROM memory the maximum number of devices that can be processed by the class is variable. **
-** After each device is discovered the resolution is set to the maximum value and a conversion is initiated. This **
-** is done as soon as possible since a conversion at maximum resolution takes up to 750ms **
-*******************************************************************************************************************/
-uint8_t DSFamily_Class::ScanForDevices() { // //
- uint8_t tempTherm[8]; // Temporary DS address array //
- _LastCommandWasConvert = false; // Set switch to false //
- reset_search(); // Reset the search status //
- ThermometersFound = 0; // Reset the number of thermometers //
- while (search(tempTherm)) { // Use the 1-Wire "search" method //
- if (tempTherm[0]==DS18B20_FAMILY || tempTherm[0]==DS18S20_FAMILY || // Only add the recognized DS- //
- tempTherm[0]==DS28EA00_FAMILY || tempTherm[0]==DS1822_FAMILY || // Family devices //
- tempTherm[0]==DS1825_FAMILY ) { // //
- EEPROM.put(E2END-((ThermometersFound+1)*8),tempTherm); // Write thermometer data to EEPROM //
- SetDeviceResolution(ThermometersFound,12); // Set to maximum resolution //
- if (ThermometersFound<=_MaxThermometers) ThermometersFound++; // Increment if we have room //
- } // of if-then we have a DS18x20 family device // otherwise we just skip the device//
- } // of while there are still new devices on the 1-Wire bus // //
- reset(); // Reset the 1-Wire bus, then //
- write_byte(DS_SKIP_ROM); // Send Skip ROM code //
- write_byte(DS_READ_POWER_SUPPLY); // Send command to read power supply//
- Parasitic = !read_bit(); // Read the power status from bus //
- DeviceStartConvert(); // Start conversion for all devices //
- return(ThermometersFound); // return number of devices detected//
-} // of method ScanForDevices //----------------------------------//
+/*!
+* @brief Use the standardized 1-Wire microLAN search mechanism to discover all DS devices
+* @details Each device has a unique 8-byte ROM address, which is stored at the end of program's EEPROM. Since each
+* Atmel chip has a different amount of memory, and the class constructor allows the user to specify a
+* number of bytes to reserve at the the beginning of the EEPROM memory the maximum number of devices that
+* can be processed by the class is variable. After each device is discovered the resolution is set to the
+* maximum value and a conversion is initiated. This is done as soon as possible since a conversion at
+* maximum resolution takes up to 750ms
+* @return number of devices found
+*/
+uint8_t DSFamily_Class::ScanForDevices()
+{
+ uint8_t tempTherm[8];
+ _LastCommandWasConvert = false;
+ reset_search(); // Reset the search status
+ ThermometersFound = 0;
+ while (search(tempTherm)) // Use the 1-Wire "search" method
+ {
+ if (tempTherm[0]==DS18B20_FAMILY || tempTherm[0]==DS18S20_FAMILY || tempTherm[0]==DS28EA00_FAMILY ||
+ tempTherm[0]==DS1822_FAMILY || tempTherm[0]==DS1825_FAMILY )
+ {
+ EEPROM.put(E2END-((ThermometersFound+1)*8),tempTherm); // Write thermometer data to EEPROM
+ SetDeviceResolution(ThermometersFound,12); // Set to maximum resolution
+ if (ThermometersFound<=_MaxThermometers) ThermometersFound++; // Increment if we have room
+ } // of if-then we have a DS18x20 family device
+ } // of while there are still new devices on the 1-Wire bus
+ reset(); // Reset the 1-Wire bus
+ write_byte(DS_SKIP_ROM); // Send Skip ROM code
+ write_byte(DS_READ_POWER_SUPPLY); // Send command to read power supply
+ Parasitic = !read_bit(); // Read the power status from bus
+ DeviceStartConvert(); // Start conversion for all devices
+ return(ThermometersFound); // return number of devices detected
+} // of method ScanForDevices
-/*******************************************************************************************************************
-** Method Read1WireScratchpad() method to read the contents of a given DS devices scratchpad from the 1-Wire **
-** microLAN into local memory. **
-*******************************************************************************************************************/
-boolean DSFamily_Class::Read1WireScratchpad(const uint8_t deviceNumber, // //
- uint8_t buffer[9]) { // //
- _LastCommandWasConvert = false; // Set switch to false //
- bool CRCStatus = false; // default to a bad reading //
- uint8_t ErrorCounter = 0; // Count number of bad readings //
- while (!CRCStatus && ErrorCounter++ < 10) { // Loop until good read or overflow //
- SelectDevice(deviceNumber); // Reset the 1-wire, address device //
- write_byte(DS_READ_SCRATCHPAD); // Request device send Scratchpad //
- for (uint8_t i=0;i<9;i++) buffer[i] = read_byte(); // read all 9 bytes sent by DS //
- CRCStatus = crc8(buffer,8) == buffer[8]; // Check to see if result is valid //
- } // of loop until good read or number of errors exceeded // //
- return(CRCStatus); // Return false if bad CRC checksum //
-} // of method Read1WireScratchpad() //----------------------------------//
+/*!
+* @brief read the scratchpad contents from a given DS device
+* @param[in] deviceNumber 1-Wire device number
+* @param[in] buffer 8-byte scratchpad contents from device
+* @return "true" if successful otherwise "false"
+*/
+boolean DSFamily_Class::Read1WireScratchpad(const uint8_t deviceNumber, uint8_t buffer[9])
+{
+ _LastCommandWasConvert = false; // Set switch to false
+ bool CRCStatus = false; // default to a bad reading
+ uint8_t ErrorCounter = 0; // Count number of bad readings
+ while (!CRCStatus && ErrorCounter++ < 10) // Loop until good read or overflow
+ {
+ SelectDevice(deviceNumber); // Reset the 1-wire, address device
+ write_byte(DS_READ_SCRATCHPAD); // Request device to send Scratchpad contents
+ for (uint8_t i = 0; i < 9; i++)
+ {
+ buffer[i] = read_byte();
+ } // for-next read each scratchpad byte
+ CRCStatus = crc8(buffer,8) == buffer[8]; // Check to see if result is valid
+ } // of loop until good read or number of errors exceeded
+ return(CRCStatus); // Return false if bad CRC checksum
+} // of method Read1WireScratchpad()
-/*******************************************************************************************************************
-** method ReadDeviceTemp() to return the current temperature value for a given device number. All devices except **
-** the DS18S20 return raw values in 0.0625°C increments, so the 0.5°C increments of the DS18S20 are converted to **
-** the same scale as the other devices. A check is done to see if there are still conversion(s) being done and a **
-** delay is made until any conversions have time to complete. We only store ony value for conversion start time, **
-** so the delay might be for another devices and might not be necessary, but the alternative is to store the **
-** conversion times for each device which would potentially consume a lot of available memory **
-*******************************************************************************************************************/
-int16_t DSFamily_Class::ReadDeviceTemp(const uint8_t deviceNumber, // //
- const bool raw) { // //
- uint8_t dsBuffer[9]; // Buffer to hold scratchpad return //
- int16_t temperature = DS_BAD_TEMPERATURE; // Holds return value //
- if (Parasitic || !_LastCommandWasConvert) { // Wait a fixed time in parasite or //
- if ((_ConvStartTime+ConversionMillis)>millis()) // If a conversion is still running //
- delay(millis()-(_ConvStartTime+ConversionMillis)); // then wait until it is finished //
- } else if (_LastCommandWasConvert) while(read_bit()==0); // bit high when conversion finished//
- if ( deviceNumber < ThermometersFound && // on a successful read from the //
- Read1WireScratchpad(deviceNumber,dsBuffer)) { // device scratchpad //
- if (ROM_NO[0]==DS1822_FAMILY) { // If DS1822 then temp is different //
- temperature = ((dsBuffer[1] << 8) | dsBuffer[0])<<3; // get the raw reading and apply //
- temperature = (temperature & 0xFFF0) + 12 - dsBuffer[6]; // value from "count remain" byte //
- } else temperature = (dsBuffer[1]<<8)|dsBuffer[0]; // Results come in 2s complement //
- if ((dsBuffer[2]^dsBuffer[3]) == 0xFF && // Apply any calibration offset //
- !raw) temperature += (int8_t)dsBuffer[2]; // if raw is not true //
- } // of if-then the read was successful // of if-then-else the DS18x20 read //
- return(temperature); // Return our computed reading //
-} // of method ReadDeviceTemp() //----------------------------------//
+/*!
+* @brief return the current temperature value for a given device number
+* @details All devices except the DS18S20 return raw values in 0.0625°C increments, so the 0.5°C increments of the
+* DS18S20 are converted to the same scale as the other devices. A check is done to see if there are still
+* conversion(s) being done and a delay is made until any conversions have time to complete. We only store
+* the value for conversion start time, so the delay might be for another devices and might not be necessary,
+* but the alternative is to store the conversion times for each device which would potentially consume a lot
+* of available memory
+* @param[in] deviceNumber 1-Wire device number
+* @param[in] raw (Optional, default "false") If set to "true" then the raw reading is returned, otherwise the
+ compensated calibrated value is returned
+* @return Temperature reading in device units
+*/
+int16_t DSFamily_Class::ReadDeviceTemp(const uint8_t deviceNumber, const bool raw)
+{
+ uint8_t dsBuffer[9];
+ int16_t temperature = DS_BAD_TEMPERATURE; // Default return is error value
+ if (Parasitic || !_LastCommandWasConvert) // Wait a fixed time in parasite or
+ {
+ if ((_ConvStartTime + ConversionMillis) > millis())
+ {
+ delay(millis() - (_ConvStartTime + ConversionMillis)); // Wait for conversion to finish
+ } // if-then-else conversion is active
+ }
+ else
+ {
+ if (_LastCommandWasConvert)
+ {
+ while (read_bit() == 0); // Loop until bit goes high after conversion has finished
+ } // if-then last command was conversion
+ } // if-then-else parasitic or conversion active
+ if ( deviceNumber < ThermometersFound && Read1WireScratchpad(deviceNumber,dsBuffer)) // Successful read from device
+ {
+ if (ROM_NO[0]==DS1822_FAMILY) // If DS1822 then temp is different
+ {
+ temperature = ((dsBuffer[1] << 8) | dsBuffer[0])<<3; // get the raw reading and apply
+ temperature = (temperature & 0xFFF0) + 12 - dsBuffer[6]; // value from "count remain" byte
+ }
+ else
+ {
+ temperature = (dsBuffer[1] << 8) | dsBuffer[0]; // Results come in 2s complement
+ } // if-then-else a DS1822
+ if ((dsBuffer[2] ^ dsBuffer[3]) == 0xFF && !raw) // Apply any calibration offset if raw is not true
+ {
+ temperature += (int8_t)dsBuffer[2];
+ } // if-then calibrated device and raw is not true
+ } // of if-then the read was successful
+ return(temperature);
+} // of method ReadDeviceTemp()
-/*******************************************************************************************************************
-** method DeviceStartConvert() to start the sampling and conversion on a device. At maximum resolution this **
-** conversion can take 750ms. If the optional deviceNumber is not specified then all device conversions are **
-** started at the same time. If the optional WaitSwitch parameter is set to "true" then call doesn't return until **
-** the conversion has completed **
-*******************************************************************************************************************/
-void DSFamily_Class::DeviceStartConvert(const uint8_t deviceNumber, // //
- const bool WaitSwitch ) { // //
- ParasiticWait(); // Wait for conversion if necessary //
- if (deviceNumber==UINT8_MAX) { // If no parameter specified, use //
- reset(); // Reset 1-wire network //
- write_byte(DS_SKIP_ROM); // Tell all devices to listen //
- } else SelectDevice(deviceNumber); // of if-then all devices or just one // //
- write_byte(DS_START_CONVERT); // Initiate temperature conversion //
- _ConvStartTime = millis(); // Store start time of conversion //
- _LastCommandWasConvert = true; // Set switch to true //
- if (WaitSwitch) // Don't return until finished //
+/*!
+* @brief Start the sampling and conversion on a device
+* @details At maximum resolution this conversion can take 750ms. If the optional deviceNumber is not specified then
+* all device conversions are started at the same time. If the optional WaitSwitch parameter is set to
+* "true" then call doesn't return until the conversion has completed
+* @param[in] deviceNumber 1-Wire device number
+* @param[in] WaitSwitch (Optional, default "false"). When "true" the call doesn't return until measurements have
+* completed
+*/
+void DSFamily_Class::DeviceStartConvert(const uint8_t deviceNumber, const bool WaitSwitch )
+{
+ ParasiticWait(); // Wait for conversion to complete if necessary
+ if (deviceNumber==UINT8_MAX) // if default for all devices
+ {
+ reset(); // Reset 1-wire network
+ write_byte(DS_SKIP_ROM); // Tell all devices to listen
+ }
+ else
+ {
+ SelectDevice(deviceNumber);
+ } // if-then-else all devices or just one
+ write_byte(DS_START_CONVERT); // Initiate temperature conversion
+ _ConvStartTime = millis(); // Store start time of conversion
+ _LastCommandWasConvert = true; // Set switch to true
+ if (WaitSwitch) // Don't return until finished
{
if (Parasitic)
{
- ParasiticWait(); // wait a fixed period when parasite//
+ ParasiticWait(); // wait a fixed period when in parasite mode
}
else
{
- while (read_bit() == 0); // Read bit goes high when finished //
+ while (read_bit() == 0); // Wait until read bit goes high when conversion finished
} // if-then-else Parasitic
} // if-then Waitswitch set
-} // of method DeviceStartConvert //----------------------------------//
+} // of method DeviceStartConvert
-/*******************************************************************************************************************
-** CalibrateDSFamily() method to calibrate all thermometers. Each DS has a persistent 2 user bytes which can be **
-** both read and updated. These can be used for triggering alarms, but in this application we are going to set **
-** these to provide a calibration offset value so that all DS devices on the 1-wire can be set to accurately **
-** show the same temperature. This only works when all of the thermometers are at the same temperature, which can **
-** be done by various methods. What temperature is used for the calibration is unimportant, although a calibration**
-** at typical operating temperatures makes the most sense. **
-** **
-** The calibration method used here is quite simple and straightforward. First, all devices are measured for a **
-** period of time defined in MEASUREMENT_ITERATIONS. The average of all readings is computed and that value is **
-** assumed to be the correct and accurate temperature reading. Each thermometer's offset to this standard value **
-** is computed and is written to the two user bytes. **
-** **
-** In order to ensure that the correct values are used at runtime, the values are written to the two user bytes **
-** so that XOR'ing them together always results in a value of 0xFF. **
-** **
-** The CalTemp optional parameter specifies the calibration temperature that all thermometers are to be adjusted **
-** to. This temperature is a signed integer in hectodegrees Celsius, so a temperature of "28.12" would be "2812". **
-** **
-*******************************************************************************************************************/
-void DSFamily_Class::Calibrate(const uint8_t iterations, // //
- const int16_t CalTemp ) { // //
- const uint8_t DS_MAX_THERMOMETERS = 32; // Specify a maximum number here //
- int64_t stats1[DS_MAX_THERMOMETERS] = {0}; // store statistics per device //
- int64_t tempSum = 0; // Stores interim values //
- int8_t offset = 0; // Stores the computed offset value //
- uint8_t ThermometersUsed = min(DS_MAX_THERMOMETERS,ThermometersFound); // Use the lower of the 2 values //
- _LastCommandWasConvert = false; // Set switch to false //
- for (uint8_t i=0;imaximumTemp) maximumTemp=deviceTemp; // if greater than minimum reset //
- } // of for-next each thermometer // //
- return(maximumTemp); // //
-} // of method MaxTemperature //----------------------------------//
+/*!
+* @brief Return the calibration setting from the device
+* @details If the calibration register 1 is equal to the XOR value of register 2 then it is assumed that a valid
+* calibration has been set and that is returned
+* @param[in] deviceNumber 1-Wire device number
+* @return calibration offset. If the calibration offset is invalid then INT8_MIN is returned
+*/
+int8_t DSFamily_Class::GetDeviceCalibration(const uint8_t deviceNumber)
+{
+ int8_t offset = INT8_MIN; // Default to an invalid value
+ uint8_t dsBuffer[9]; // Temporary scratchpad buffer
+ _LastCommandWasConvert = false; // Set switch to false
+ Read1WireScratchpad(deviceNumber,dsBuffer); // Read from the device scratchpad
+ if ((dsBuffer[2] ^ dsBuffer[3]) == 0xFF)
+ {
+ offset = (int8_t)dsBuffer[2];
+ } // if-then a valid calibration
+ return (offset);
+} // of method GetDeviceCalibration()
-/*******************************************************************************************************************
-** Method AvgTemperature reads all current device temperatures and returns the average value. If the optional **
-** skipDeviceNumber is specified then that device number is skipped; this is used when one of the thermometers is **
-** out-of-band **
-*******************************************************************************************************************/
-int16_t DSFamily_Class::AvgTemperature(const uint8_t skipDeviceNumber){ // Average temperature of devices//
- int16_t AverageTemp = 0; // return value starts at 0 //
- for (uint8_t i=0;i12) resolution = 12; // Default to full resolution //
- switch (resolution) { // Now select which action to do //
- case 12: // When 12 bits of precision used //
- ConversionMillis = DS_12b_CONVERSION_TIME; // Set the conversion time //
- break; //----------------------------------//
- case 11: // When 12 bits of precision used //
- ConversionMillis = DS_11b_CONVERSION_TIME; // Set the conversion time //
- break; //----------------------------------//
- case 10: // When 12 bits of precision used //
- ConversionMillis = DS_10b_CONVERSION_TIME; // Set the conversion time //
- break; //----------------------------------//
- case 9: // When 12 bits of precision used //
- ConversionMillis = DS_9b_CONVERSION_TIME; // Set the conversion time //
- break; //----------------------------------//
- default: // Otherwise //
- ConversionMillis = DS_12b_CONVERSION_TIME; // Set the conversion time //
- } // of switch statement for precision //----------------------------------//
- resolution = (resolution-9)<<5; // Shift resolution bits over //
- Read1WireScratchpad(deviceNumber,dsBuffer); // Read device scratchpad //
- SelectDevice(deviceNumber); // Reset 1-wire, address device //
- write_byte(DS_WRITE_SCRATCHPAD); // Write scratchpad, send 3 bytes //
- write_byte(dsBuffer[DS_USER_BYTE_1]); // Restore the old user byte 1 //
- write_byte(dsBuffer[DS_USER_BYTE_2]); // Restore the old user byte 2 //
- write_byte(resolution); // Set configuration register //
- write_byte(DS_COPY_SCRATCHPAD); // Copy scratchpad to NV memory //
- delay(DS_MAX_NV_CYCLE_TIME); // Give the DS18x20 time to process //
-} // of method SetDeviceResolution //----------------------------------//
+/*!
+* @brief return the 8-byte ROM address buffer
+* @param[in] deviceNumber 1-Wire device number
+* @param[out] ROMBuffer 8-byte ROM address buffer of device
+*/
+void DSFamily_Class::GetDeviceROM(const uint8_t deviceNumber, uint8_t ROMBuffer[8])
+{
+ _LastCommandWasConvert = false;
+ for (uint8_t i = 0; i < 8; i++)
+ {
+ ROMBuffer[i] = EEPROM.read(i + E2END - ((deviceNumber + 1) * 8));
+ } // for-next each byte in the buffer
+} // of method GetDeviceROM()
-/*******************************************************************************************************************
-** Method SetUserBytes to set the user bytes 1 and 2 to the calibration computed **
-*******************************************************************************************************************/
-uint8_t DSFamily_Class::GetDeviceResolution(const uint8_t deviceNumber) { // //
- uint8_t resolution; // Store the return value //
- uint8_t dsBuffer[9]; // Hold scratchpad return values //
- _LastCommandWasConvert = false; // Set switch to false //
- Read1WireScratchpad(deviceNumber,dsBuffer); // Read from the device scratchpad //
- resolution = (dsBuffer[DS_CONFIG_BYTE]>>5)+9; // get bits 6&7 from the config byte//
- return(resolution); // //
-} // of method GetDeviceResolution() //----------------------------------//
+/*!
+* @brief reads all current device temperatures and returns the lowest value
+* @details If the optional skipDeviceNumber is specified then that device number is skipped; this is used when
+* one of the thermometers is out-of-band - i.e. if it is attached to an evaporator plate and reads much
+* lower than the others.
+* @param[in] skipDeviceNumber Device number to skip, defaults to no skipped device
+* @return Minimum temperature
+*/
+int16_t DSFamily_Class::MinTemperature(uint8_t skipDeviceNumber)
+{
+ int16_t deviceTemp;
+ int16_t minimumTemp = INT16_MAX; // Starts at highest possible value
+ for (uint8_t i=0;i maximumTemp)
+ {
+ maximumTemp = deviceTemp;
+ } // if-then not skipped device and greater than current max
+ } // of for-next each thermometer
+ return(maximumTemp);
+} // of method MaxTemperature
-/*******************************************************************************************************************
-** 1-Wire: Method reset_search(). You need to use this function to start a search again from the beginning. You **
-** do not need to do it for the first search, though you could. **
-*******************************************************************************************************************/
-void DSFamily_Class::reset_search() { // //
- LastDiscrepancy = 0; // //
- LastDeviceFlag = FALSE; // //
- LastFamilyDiscrepancy = 0; // //
- for(int i = 7; ; i--) { // //
- ROM_NO[i] = 0; // //
- if ( i == 0) break; // //
- } // of for-next each ROM byte // //
-} // of method reset_search //----------------------------------//
+/*!
+* @brief reads all current device temperatures and returns the average value
+* @details If the optional skipDeviceNumber is specified then that device number is skipped; this is used when
+* one of the thermometers is out-of-band - i.e. if it is attached to a heat source or evaporator plate
+* and reads much lower or higher than the others.
+* @param[in] skipDeviceNumber Device number to skip, defaults to no skipped device
+* @return Maximum temperature
+*/
+int16_t DSFamily_Class::AvgTemperature(const uint8_t skipDeviceNumber)
+{
+ int16_t AverageTemp = 0;
+ for (uint8_t i=0;i12) resolution = 12; // Default to full resolution
+ switch (resolution)
+ {
+ case 12:
+ ConversionMillis = DS_12b_CONVERSION_TIME;
+ break;
+ case 11:
+ ConversionMillis = DS_11b_CONVERSION_TIME;
+ break;
+ case 10:
+ ConversionMillis = DS_10b_CONVERSION_TIME;
+ break;
+ case 9:
+ ConversionMillis = DS_9b_CONVERSION_TIME;
+ break;
+ default:
+ ConversionMillis = DS_12b_CONVERSION_TIME;
+ } // of switch statement for precision
+ resolution = (resolution-9)<<5; // Shift resolution bits over
+ Read1WireScratchpad(deviceNumber,dsBuffer); // Read device scratchpad
+ SelectDevice(deviceNumber); // Reset 1-wire, address device
+ write_byte(DS_WRITE_SCRATCHPAD); // Write scratchpad, send 3 bytes
+ write_byte(dsBuffer[DS_USER_BYTE_1]); // Restore the old user byte 1
+ write_byte(dsBuffer[DS_USER_BYTE_2]); // Restore the old user byte 2
+ write_byte(resolution); // Set configuration register
+ write_byte(DS_COPY_SCRATCHPAD); // Copy scratchpad to NV memory
+ delay(DS_MAX_NV_CYCLE_TIME); // Give the DS18x20 time to process
+} // of method SetDeviceResolution
-/*******************************************************************************************************************
-** 1-Wire: Method read_bit(). Read a bit. Port & bit is used to cut lookup time and provide more certain timing. **
-*******************************************************************************************************************/
-uint8_t DSFamily_Class::read_bit(void) { // //
- IO_REG_TYPE mask=bitmask; // Register mask //
- volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg; // Register //
- uint8_t r; // Return bit //
- noInterrupts(); // Disable interrupts for now //
- DIRECT_MODE_OUTPUT(reg, mask); // //
- DIRECT_WRITE_LOW(reg, mask); // //
- delayMicroseconds(3); // Wait //
- DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise//
- delayMicroseconds(10); // Wait //
- r = DIRECT_READ(reg, mask); // //
- interrupts(); // Enable interrupts again //
- delayMicroseconds(53); // Wait //
- return r; // Return result //
-} // of method read_bit() //----------------------------------//
+/*!
+* @brief Get the device resolution
+* @param[in] deviceNumber 1-Wire device number
+* @return number of bits resolution (9, 10, 11 or 12)
+*/
+uint8_t DSFamily_Class::GetDeviceResolution(const uint8_t deviceNumber)
+{
+ uint8_t resolution, dsBuffer[9];
+ _LastCommandWasConvert = false; // Set switch to false
+ Read1WireScratchpad(deviceNumber,dsBuffer); // Read from the device scratchpad
+ resolution = (dsBuffer[DS_CONFIG_BYTE]>>5)+9; // get bits 6&7 from the config byte
+ return(resolution);
+} // of method GetDeviceResolution()
-/*******************************************************************************************************************
-** 1-Wire: Method write_byte(). Write a byte. The writing code uses the active drivers to raise the pin high, if **
-** you need power after the write (e.g. DS18S20 in parasite power mode) then set 'power' to 1, otherwise the pin **
-** will go tri-state at the end of the write to avoid heating in a short or other mishap. **
-*******************************************************************************************************************/
-void DSFamily_Class::write_byte(uint8_t v, uint8_t power) { // //
- uint8_t bitMask; // Bit mask //
- for (bitMask = 0x01; bitMask; bitMask <<= 1) write_bit( (bitMask & v)?1:0); // Write bits until empty //
- if ( !power) { // Set pin in parasite mode //
- noInterrupts(); // Disable interrupts for now //
- DIRECT_MODE_INPUT(baseReg, bitmask); // //
- DIRECT_WRITE_LOW(baseReg, bitmask); // //
- interrupts(); // Enable interrupts again //
- } // of if-then we have parasite mode // //
-} // of method write_byte() //----------------------------------//
+/*!
+* @brief reads all current device temperatures and returns the standard deviation
+* @details If the optional skipDeviceNumber is specified then that device number is skipped; this is used when
+* one of the thermometers is out-of-band and should be ignored
+* @param[in] skipDeviceNumber Device number to skip, defaults to no skipped device
+* @return Floating point standard deviation
+*/
+float DSFamily_Class::StdDevTemperature(const uint8_t skipDeviceNumber)
+{
+ float StdDev = 0;
+ int16_t AverageTemp = AvgTemperature(skipDeviceNumber); // Compute the average
+ for (uint8_t i=0;i0); // //
- else // if equal to last pick then 1, if //
- search_direction = (id_bit_number == LastDiscrepancy); // not then pick 0 //
- if (search_direction == 0) { // if 0 was picked then record its //
- last_zero = id_bit_number; // position in LastZero //
- if (last_zero < 9) LastFamilyDiscrepancy = last_zero; // check for Last discrepancy //
- } // of if-then search direction is 0 // //
- } // of if-then-else all devices have 0 or 1 // //
- if (search_direction == 1) // set or clear the bit in the ROM //
- ROM_NO[rom_byte_number] |= rom_byte_mask; // byte rom_byte_number with mask //
- else // rom_byte_mask //
- ROM_NO[rom_byte_number] &= ~rom_byte_mask; // //
- write_bit(search_direction); // serial number search direction //
- id_bit_number++; // increment the byte counter //
- rom_byte_mask <<= 1; // id_bit_number&shift rom_byte_mask//
- if (rom_byte_mask == 0) { // if the mask is 0 then go to new //
- rom_byte_number++; // SerialNum byte rom_byte_number //
- rom_byte_mask = 1; // and reset mask //
- } // of if-then mask is 0 // //
- } // of if-then-else device still found // //
- } // of loop until all devices found // //
- while(rom_byte_number < 8); // loop until through ROM bytes 0-7 //
- if (!(id_bit_number < 65)) { // if the search was successful then//
- LastDiscrepancy = last_zero; // search successful so set //
- if (LastDiscrepancy == 0) LastDeviceFlag = TRUE; // check for last device //
- search_result = TRUE; // //
- } // of if-then search was successful // //
- } // of if-then there are still devices to be found // //
- if (!search_result || !ROM_NO[0]) { // if no device found then reset //
- LastDiscrepancy = 0; // counters so next 'search' will //
- LastDeviceFlag = FALSE; // be like a first //
- LastFamilyDiscrepancy = 0; // //
- search_result = FALSE; // //
- } // of if-then no device found // //
- for (int i = 0; i < 8; i++) newAddr[i] = ROM_NO[i]; // Copy result buffer //
- return search_result; // Return results //
-} // of method search() //----------------------------------//
+/*!
+* @brief Write a bit to 1-wire
+* @details Port & bit is used to cut lookup time and provide more certain timing
+* @param[in] v Only the LSB is used as the bit to write to 1-Wire
+*/
+void DSFamily_Class::write_bit(uint8_t v)
+{
+ IO_REG_TYPE mask=bitmask; // Register mask
+ volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg; // Register
+ if (v & 1) // If writing a "1"
+ {
+ noInterrupts(); // Disable interrupts for now
+ DIRECT_WRITE_LOW(reg, mask);
+ DIRECT_MODE_OUTPUT(reg, mask); // drive output low
+ delayMicroseconds(10); // Wait
+ DIRECT_WRITE_HIGH(reg, mask); // drive output high
+ interrupts(); // Enable interrupts again
+ delayMicroseconds(55); // Wait
+ }
+ else
+ {
+ noInterrupts(); // Disable interrupts for now
+ DIRECT_WRITE_LOW(reg, mask);
+ DIRECT_MODE_OUTPUT(reg, mask); // drive output low
+ delayMicroseconds(65); // Wait
+ DIRECT_WRITE_HIGH(reg, mask); // drive output high
+ interrupts(); // Enable interrupts again
+ delayMicroseconds(5); // Wait
+ } // of if-then we have a "true" to write
+} // of method write_bit()
-/*******************************************************************************************************************
-** 1-Wire: Method crc8(). Compute the 8 bit crc of the returned buffer. This method uses the iterative method, **
-** which is slower than the default 1-Wire table lookup but that uses 255 bytes of program memory. **
-*******************************************************************************************************************/
-uint8_t DSFamily_Class::crc8(const uint8_t *addr, uint8_t len) { // //
- uint8_t crc = 0; // Return crc value //
- while (len--) { // //
- uint8_t inbyte = *addr++; // //
- for (uint8_t i = 8; i; i--) { // //
- uint8_t mix = (crc ^ inbyte) & 0x01; // //
- crc >>= 1; // //
- if (mix) crc ^= 0x8C; // //
- inbyte >>= 1; // //
- } // of for-next each byte in the ROM // //
- } // of while data still be to computed // //
- return crc; // return computed CRC value //
-} // of method crc8() //----------------------------------//
+/*!
+* @brief Read a bit from 1-wire
+* @details Port & bit is used to cut lookup time and provide more certain timing
+* @return single bit where only the LSB is used as the bit that was read
+*/
+uint8_t DSFamily_Class::read_bit(void)
+{
+ IO_REG_TYPE mask=bitmask; // Register mask
+ volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg; // Register
+ uint8_t r; // Return bit
+ noInterrupts(); // Disable interrupts for now
+ DIRECT_MODE_OUTPUT(reg, mask);
+ DIRECT_WRITE_LOW(reg, mask);
+ delayMicroseconds(3); // Wait
+ DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise it up again
+ delayMicroseconds(10); // Wait
+ r = DIRECT_READ(reg, mask);
+ interrupts(); // Enable interrupts again
+ delayMicroseconds(53); // Wait
+ return r; // Return result
+} // of method read_bit()
-/*******************************************************************************************************************
-** Method ParasiticWait(). Any parasitically device needs to have a strong power pullup on the 1-Wire data line **
-** during conversion. This means that the whole 1-Wire microLAN is effectively blocked during the rather lengthy **
-** conversion time; since using the bus would cause the parasitically powered device to abort conversion. There- **
-** this function will wait until the last conversion request has had enough time to complete. The wait time might **
-** be unnecessary, but since we only track the last conversion start rather than track each device independently **
-** this is the best we can do. **
-*******************************************************************************************************************/
-void DSFamily_Class::ParasiticWait() { // //
- if (Parasitic && ((_ConvStartTime+ConversionMillis)>millis())) { // If parasitic & active conversion //
- delay((_ConvStartTime+ConversionMillis)-millis()); // then wait until it is finished //
- } // of if-then we have a parasitic device on the 1-Wire // //
-} // of method ParasiticWait() //----------------------------------//
+/*!
+* @brief Write a byte to 1-wire
+* @details The writing code uses the active drivers to raise the pin high, if you need power after the write
+* (e.g. DS18S20 in parasite power mode) then set 'power' to 1, otherwise the pin will go tri-state at
+* the end of the write to avoid heating in a short or other mishap
+* @param[in] v Byte to write
+* @param[in] power Boolean switch set to "true" when powered and "false" in parasite mode
+*/
+void DSFamily_Class::write_byte(uint8_t v, uint8_t power)
+{
+ uint8_t bitMask;
+ for (bitMask = 0x01; bitMask; bitMask <<= 1)
+ {
+ write_bit((bitMask & v) ? 1 : 0); // Write bits until empty
+ } // for-next each bit
+ if ( !power)
+ {
+ noInterrupts();
+ DIRECT_MODE_INPUT(baseReg, bitmask);
+ DIRECT_WRITE_LOW(baseReg, bitmask);
+ interrupts();
+ } // of if-then we have parasite mode
+} // of method write_byte()
+
+/*!
+* @brief Read a byte from 1-wire
+* @return byte read from 1-Wire bus
+*/
+uint8_t DSFamily_Class::read_byte()
+{
+ uint8_t bitMask;
+ uint8_t r = 0;
+ for (bitMask = 0x01; bitMask; bitMask <<= 1)
+ {
+ if ( read_bit()) r |= bitMask; // For each bit in the byte read bit into correct position
+ } // of for-next each bit in the byte
+ return r;
+} // of method read_byte()
+
+/*!
+* @brief Do a 1-Wire ROM Select
+* @param[in] 8-Byte ROM buffer
+*/
+void DSFamily_Class::select(const uint8_t rom[8])
+{
+ write_byte(DS_SELECT_ROM); // Send Select ROM code
+ for (uint8_t i = 0; i < 8; i++)
+ {
+ write_byte(rom[i]); // Send the ROM address bytes
+ } // for-next each byte in ROM buffer
+} // of method select()
+
+/*!
+* @brief Search the 1-Wire microLAN using the Dallas Semiconductor search algorith and code
+* @details Perform a search. If this function returns a '1' then it has enumerated the next device and you may
+* retrieve the ROM from the OneWire::address variable. If there are no devices, no further devices, or
+* something horrible happens in the middle of the enumeration then a 0 is returned. If a new device is
+* found then its address is copied to newAddr. Use DSFamily_Class::reset_search() to start over. **
+** Return
+* @param[in] newAddr 8-Byte ROM Buffer
+* @return TRUE - device found, ROM number in ROM_NO buffer, FALSE - device not found, end of search
+*/
+uint8_t DSFamily_Class::search(uint8_t *newAddr)
+{
+ uint8_t id_bit_number, last_zero, rom_byte_number, search_result, id_bit, cmp_id_bit;
+ unsigned char rom_byte_mask, search_direction;
+ id_bit_number = 1; // initialize values for searching
+ last_zero = 0;
+ rom_byte_number = 0;
+ rom_byte_mask = 1;
+ search_result = 0;
+ if (!LastDeviceFlag) // if last call was not the last one
+ {
+ if (!reset())
+ {
+ LastDiscrepancy = 0;
+ LastDeviceFlag = false;
+ LastFamilyDiscrepancy = 0;
+ return false;
+ } // of if-then we have a reset
+ write_byte(DS_SEARCH); // issue the search command
+ do // loop to do the search
+ {
+ id_bit = read_bit(); // read a bit
+ cmp_id_bit = read_bit(); // and then the complement
+ if ((id_bit == 1) && (cmp_id_bit == 1)) break; // check for no devices on 1-wire
+ else
+ {
+ if (id_bit != cmp_id_bit) search_direction = id_bit; // all devices coupled have 0 or 1
+ else
+ {
+ // bit write value for search if this discrepancy is before the Last Discrepancy on a previous next
+ // then pick the same as last time
+ if (id_bit_number < LastDiscrepancy)
+ {
+ search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
+ }
+ else
+ {
+ // if equal to last pick then 1, if not then pick 0
+ search_direction = (id_bit_number == LastDiscrepancy);
+ } // if-then-else
+ if (search_direction == 0) // if 0 was picked then record its position in LastZero
+ {
+ last_zero = id_bit_number;
+ if (last_zero < 9) LastFamilyDiscrepancy = last_zero;
+ } // of if-then search direction is 0
+ } // of if-then-else all devices have 0 or 1
+ if (search_direction == 1)// set or clear the bit in the ROM
+ {
+ ROM_NO[rom_byte_number] |= rom_byte_mask; // byte rom_byte_number with mask
+ }
+ else
+ {
+ ROM_NO[rom_byte_number] &= ~rom_byte_mask;
+ }
+ write_bit(search_direction); // serial number search direction
+ id_bit_number++; // increment the byte counter
+ rom_byte_mask <<= 1; // id_bit_number & shift rom_byte_mask
+ if (rom_byte_mask == 0) // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
+ {
+ rom_byte_number++;
+ rom_byte_mask = 1;
+ } // of if-then mask is 0
+ } // of if-then-else device still found
+ } // of loop until all devices found
+ while(rom_byte_number < 8); // loop until through ROM bytes 0-7
+
+ if (!(id_bit_number < 65)) // if the search was successful then search successful so set
+ {
+ LastDiscrepancy = last_zero;
+ if (LastDiscrepancy == 0) LastDeviceFlag = true; // check for last device
+ search_result = true;
+ } // of if-then search was successful
+ } // of if-then there are still devices to be found
+ if (!search_result || !ROM_NO[0]) // if the search was successful then
+ {
+ LastDiscrepancy = 0; // Set counters so next 'search' will be like a first
+ LastDeviceFlag = false;
+ LastFamilyDiscrepancy = 0;
+ search_result = false;
+ } // of if-then no device found
+ for (int i = 0; i < 8; i++)
+ newAddr[i] = ROM_NO[i]; // Copy result buffer
+ // for-next each byte in buffer
+ return search_result;
+} // of method search()
+
+/*!
+* @brief Compute the 8 bit crc of the returned buffer
+* @details This method uses the iterative method, which is slower than the default 1-Wire table lookup but that
+* uses 255 bytes of scant program memory.
+* @param[in] addr Pointer to buffer
+* @param[in] len Length of buffer
+* @return computed crc8
+*/
+uint8_t DSFamily_Class::crc8(const uint8_t *addr, uint8_t len)
+{
+ uint8_t crc = 0;
+ while (len--)
+ {
+ uint8_t inbyte = *addr++;
+ for (uint8_t i = 8; i; i--)
+ {
+ uint8_t mix = (crc ^ inbyte) & 0x01;
+ crc >>= 1;
+ if (mix) crc ^= 0x8C;
+ inbyte >>= 1;
+ } // of for-next each byte in the ROM
+ } // of while data still be to computed
+ return crc;
+} // of method crc8()
+
+/*!
+* @brief Wait when parasitically powered devices are converting
+* @details Any parasitically device needs to have a strong power pullup on the 1-Wire data line during conversion.
+* This means that the whole 1-Wire microLAN is effectively blocked during the rather lengthy conversion
+* time; since using the bus would cause the parasitically powered device to abort conversion. Therefore
+* this function will wait until the last conversion request has had enough time to complete. The wait
+* time might be unnecessary, but since we only track the last conversion start rather than track each
+* device independently this is the best we can do.
+*/
+void DSFamily_Class::ParasiticWait()
+{
+ if (Parasitic && ((_ConvStartTime+ConversionMillis)>millis()))
+ {
+ delay((_ConvStartTime+ConversionMillis)-millis()); // then delay until it is finished
+ } // of if-then we have a parasitic device on the 1-Wire
+} // of method ParasiticWait()
diff --git a/src/DSFamily.h b/src/DSFamily.h
index b7d7cdd..6897383 100644
--- a/src/DSFamily.h
+++ b/src/DSFamily.h
@@ -1,181 +1,187 @@
-/*******************************************************************************************************************
-** Class definition header for the DSFamily class. Defines the methods and variables in the class **
-** **
-** The goal of this class is to simplify using multiple DSFamily 1-Wire thermometers from an Arduino. Particularly**
-** when the number of attached devices is unknown, quite a bit of valuable variable memory is consumed when **
-** allocating an array of {n} times the 8 Byte (64bit) Unique address; e.g. 128Bytes of storage would normally **
-** be reserved if there can be up to 16 1-Wire devices. **
-** **
-** This class stores this address information at the end of the EEPROM memory, optionally reserving space at the **
-** beginning of EEPROM for other applications. Thus the maximum number of devices that can be processed depends **
-** upon the space reserved and the space available on the given Atmel processor. While the number of write-cycles **
-** to EEPROM should be limited to 10,000; the order of the 1-Wire devices is deterministic and the EEPROM.h **
-** library calls will check to make sure that no writes are performed if the data hasn't changed, so using EEPROM **
-** for this functionality is not an issue as few, if any, writes are done after the program has been run with a **
-** given configuration. **
-** **
-** Access to the devices is done with an index number rather than the 64-Bit unique address, simplifying using **
-** the device. Several methods are built into the library to simplify basic operations on multiple thermometers, **
-** including allowing one of the thermometer readings to be ignored - important if one of the devices is placed **
-** elsewhere - i.e. one thermometer is on the board to measure ambient temperature, or one thermometer is placed **
-** directly on the evaporator plate in a refrigerator or freezer and is thus much colder than the others. **
-** **
-** While the DS Family of thermometers are quite accurate, there can still be significant variations between **
-** readings. The class contains a calibration routine which assumes that all of the devices are at the same **
-** temperature and will use the DS-Family's 2 User-definable bytes to store offset calibration information which **
-** ensures a significant improvement in accuracy. **
-** **
-** The Maxim DSFamily of thermometers use the 1-Wire microLAN protocol. There is an excellent library for 1-Wire, **
-** written by Paul Stoffregen and located at http://www.pjrc.com/teensy/td_libs_OneWire.html. There is also an **
-** informative page at http://playground.arduino.cc/Learning/OneWire describing how to use the library. As there **
-** are parts of the code that are unnecessary for this DS implementation and in order to make this library self- **
-** sufficient, the code from version 2.0 (extracted 2016-11-23), has been included in this library. **
-** **
-** Although programming for the Arduino and in c/c++ is new to me, I'm a professional programmer and have learned,**
-** over the years, that it is much easier to ignore superfluous comments than it is to decipher non-existent ones;**
-** so both my comments and variable names tend to be verbose. The code is written to fit in the first 80 spaces **
-** and the comments start after that and go to column 117 - allowing the code to be printed in A4 landscape mode. **
-** **
-** GNU General Public License **
-** ========================== **
-** This program is free software: you can redistribute it and/or modify it under the terms of the GNU General **
-** Public License as published by the Free Software Foundation, either version 3 of the License, or (at your **
-** option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY **
-** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
-** GNU General Public License for more details. You should have received a copy of the GNU General Public License **
-** along with this program. If not, see . **
-** **
-** Vers. Date Developer Comments **
-** ====== ========== ============================= ============================================================== **
-** 1.0.7 2018-06-26 https://github.com/SV-Zanshin Packaging and documentation changes, optimiyed EEPROM **
-** 1.0.6 2018-06-25 https://github.com/SV-Zanshin Documentation changes **
-** 1.0.5 2017-07-31 https://github.com/SV-Zanshin Only function prototypes may have default values as this **
-** may cause compiler errors. **
-** 1.0.4 2016-12-29 https://github.com/SV-Zanshin Added error loop to Read1WireScratchpad(), corrected **
-** DS18S20 call in ReadDeviceTemp() to avoid false temps **
-** 1.0.3 2016-12-16 https://github.com/SV-Zanshin Added optional CalibrationTemp to Calibrate function **
-** 1.0.2 2016-12-03 https://github.com/SV-Zanshin Added optional ReadDeviceTemp "WaitSwitch", minimized waits **
-** 1.0.1 2016-12-02 https://github.com/SV-Zanshin Added delays for ReadDeviceTemp() and when a parasitic **
-** device is present **
-** 1.0.0 2016-12-01 https://github.com/SV-Zanshin Initial release **
-** 1.0.b5 2016-11-30 https://github.com/SV-Zanshin Moved 1-Wire calls to private, refactored some of the calls **
-** 1.0.b4 2016-11-29 https://github.com/SV-Zanshin Included sections of the 1-Wire library, see above **
-** 1.0.b3 2016-11-23 https://github.com/SV-Zanshin Refactored class naming DS18B20 to support multiple types **
-** 1.0.b2 2016-11-14 https://github.com/SV-Zanshin Made ScanForDevices return the number of devices found **
-** 1.0.b1 2016-11-10 https://github.com/SV-Zanshin Added SRAM template functions to read/write efficiently **
-*******************************************************************************************************************/
-#include "Arduino.h" // Arduino data type definitions //
-#include // Access the EEPROM memory //
-#if ARDUINO >= 100 // Include depending on version //
- #include "Arduino.h" // delayMicroseconds, //
-#else // digitalPinToBitMask, etc. //
- #include "WProgram.h" // for delayMicroseconds //
- #include "pins_arduino.h" // for digitalPinToBitMask, etc //
-#endif // //
-#define FALSE 0 // FALSE and TRUE used by 1-Wire //
-#define TRUE 1 // library code //
-#if defined(__AVR__) // Platform specific I/O definitions//
- #define PIN_TO_BASEREG(OneWirePin) (portInputRegister(digitalPinToPort(OneWirePin)))// //
- #define PIN_TO_BITMASK(OneWirePin) (digitalPinToBitMask(OneWirePin)) // //
- #define IO_REG_TYPE uint8_t // //
- #define IO_REG_ASM asm("r30") // //
- #define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0) // //
- #define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) &= ~(mask)) // //
- #define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+1)) |= (mask)) // //
- #define DIRECT_WRITE_LOW(base, mask) ((*((base)+2)) &= ~(mask)) // //
- #define DIRECT_WRITE_HIGH(base, mask) ((*((base)+2)) |= (mask)) // //
-#elif defined(__MK20DX128__) // //
- #define PIN_TO_BASEREG(OneWirePin) (portOutputRegister(OneWirePin)) // //
- #define PIN_TO_BITMASK(OneWirePin) (1) // //
- #define IO_REG_TYPE uint8_t // //
- #define IO_REG_ASM // //
- #define DIRECT_READ(base, mask) (*((base)+512)) // //
- #define DIRECT_MODE_INPUT(base, mask) (*((base)+640) = 0) // //
- #define DIRECT_MODE_OUTPUT(base, mask) (*((base)+640) = 1) // //
- #define DIRECT_WRITE_LOW(base, mask) (*((base)+256) = 1) // //
- #define DIRECT_WRITE_HIGH(base, mask) (*((base)+128) = 1) // //
-#elif defined(__SAM3X8E__) // //
+/*! @file DSFamily.h
+
+ @mainpage Arduino Library Header to access the DS Family of 1-wire temperature sensors
+
+ @section intro_section Description
+
+The goal of this class is to simplify using multiple DSFamily 1-Wire thermometers from an Arduino. Particularly
+when the number of attached devices is unknown, quite a bit of valuable variable memory is consumed when
+allocating an array of {n} times the 8 Byte (64bit) Unique address; e.g. 128Bytes of storage would normally
+be reserved if there can be up to 16 1-Wire devices.\n\n
+
+This class stores this address information at the end of the EEPROM memory, optionally reserving space at the
+beginning of EEPROM for other applications. Thus the maximum number of devices that can be processed depends upon
+the space reserved and the space available on the given Atmel processor. While the number of write-cycles to
+EEPROM should be limited to 10,000; the order of the 1-Wire devices is deterministic and the EEPROM.h library
+calls will check to make sure that no writes are performed if the data hasn't changed, so using EEPROM for this
+functionality is not an issue as few, if any, writes are done after the program has been run with a given
+configuration.\n\n
+
+Access to the devices is done with an index number rather than the 64-Bit unique address, simplifying using the
+device. Several methods are built into the library to simplify basic operations on multiple thermometers,
+including allowing one of the thermometer readings to be ignored - important if one of the devices is placed
+elsewhere - i.e. one thermometer is on the board to measure ambient temperature, or one thermometer is placed
+directly on the evaporator plate in a refrigerator or freezer and is thus much colder than the others.\n\n
+
+While the DS Family of thermometers are quite accurate, there can still be significant variations between readings.
+The class contains a calibration routine which assumes that all of the devices are at the same temperature and
+will use the DS-Family's 2 User-definable bytes to store offset calibration information which ensures a significant
+improvement in accuracy.\n\n
+
+The Maxim DSFamily of thermometers use the 1-Wire microLAN protocol. There is an excellent library for 1-Wire,
+written by Paul Stoffregen and located at http://www.pjrc.com/teensy/td_libs_OneWire.html. There is also an
+informative page at http://playground.arduino.cc/Learning/OneWire describing how to use the library. As there
+are parts of the code that are unnecessary for this DS implementation and in order to make this library self-
+sufficient, the code from version 2.0 (extracted 2016-11-23), has been included in this library.
+
+@section license GNU General Public License v3.0
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General
+Public License as published by the Free Software Foundation, either version 3 of the License, or (at your
+option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details. You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+
+@section author Author
+
+Written by Arnd\@SV-Zanshin
+
+@section versions Changelog
+
+Version| Date | Developer | Comments
+------ | ---------- | ----------------------------- | --------
+1.0.5 | 2019-01-26 | https://github.com/SV-Zanshin | Issue #4 - converted documentation to doxygen
+
+1.0.8 | 2019-01-27 | https://github.com/SV-Zanshin | Issue #4 - Convert to Doxygen format
+1.0.7 | 2018-06-26 | https://github.com/SV-Zanshin | Packaging and documentation changes, optimized EEPROM
+1.0.6 |2018-06-25 | https://github.com/SV-Zanshin | Documentation changes
+1.0.5 | 2017-07-31 | https://github.com/SV-Zanshin | Only function prototypes may have default values as this
+ may cause compiler errors.
+1.0.4 | 2016-12-29 | https://github.com/SV-Zanshin | Added error loop to Read1WireScratchpad(), corrected
+ DS18S20 call in ReadDeviceTemp() to avoid false temps
+1.0.3 | 2016-12-16 | https://github.com/SV-Zanshin | Added optional CalibrationTemp to Calibrate function
+1.0.2 | 2016-12-03 | https://github.com/SV-Zanshin | Added optional ReadDeviceTemp "WaitSwitch", minimized waits
+1.0.1 | 2016-12-02 | https://github.com/SV-Zanshin | Added delays for ReadDeviceTemp() and when a parasitic device
+ is present
+1.0.0 | 2016-12-01 | https://github.com/SV-Zanshin | Initial release
+1.0.b5 | 2016-11-30 | https://github.com/SV-Zanshin | Moved 1-Wire calls to private, refactored some of the calls
+1.0.b4 | 2016-11-29 | https://github.com/SV-Zanshin | Included sections of the 1-Wire library, see above
+1.0.b3 | 2016-11-23 | https://github.com/SV-Zanshin | Refactored class naming DS18B20 to support multiple types
+1.0.b2 | 2016-11-14 | https://github.com/SV-Zanshin | Made ScanForDevices return the number of devices found
+1.0.b1 | 2016-11-10 | https://github.com/SV-Zanshin | Added SRAM template functions to read/write efficiently
+*/
+
+#include // Access the AVR EEPROM memory
+#if ARDUINO >= 100 // Include depending on version
+ #include "Arduino.h"
+#else
+ #include "WProgram.h"
+ #include "pins_arduino.h" // for digitalPinToBitMask, etc.
+#endif
+#if defined(__AVR__) // Platform specific I/O definitions
+ #define PIN_TO_BASEREG(OneWirePin) (portInputRegister(digitalPinToPort(OneWirePin)))
+ #define PIN_TO_BITMASK(OneWirePin) (digitalPinToBitMask(OneWirePin))
+ #define IO_REG_TYPE uint8_t
+ #define IO_REG_ASM asm("r30")
+ #define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
+ #define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) &= ~(mask))
+ #define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+1)) |= (mask))
+ #define DIRECT_WRITE_LOW(base, mask) ((*((base)+2)) &= ~(mask))
+ #define DIRECT_WRITE_HIGH(base, mask) ((*((base)+2)) |= (mask))
+#elif defined(__MK20DX128__)
+ #define PIN_TO_BASEREG(OneWirePin) (portOutputRegister(OneWirePin))
+ #define PIN_TO_BITMASK(OneWirePin) (1)
+ #define IO_REG_TYPE uint8_t
+ #define IO_REG_ASM
+ #define DIRECT_READ(base, mask) (*((base)+512))
+ #define DIRECT_MODE_INPUT(base, mask) (*((base)+640) = 0)
+ #define DIRECT_MODE_OUTPUT(base, mask) (*((base)+640) = 1)
+ #define DIRECT_WRITE_LOW(base, mask) (*((base)+256) = 1)
+ #define DIRECT_WRITE_HIGH(base, mask) (*((base)+128) = 1)
+#elif defined(__SAM3X8E__)
/*****************************************************************************************************************
** Arduino 1.5.1 may have a bug in delayMicroseconds() on Arduino Due. If you have trouble with OneWire on the **
** Arduino Due, please check the status of delayMicroseconds() before reporting a bug in OneWire! See URL **
** http://arduino.cc/forum/index.php/topic,141030.msg1076268.html#msg1076268 for details **
*****************************************************************************************************************/
- #define PIN_TO_BASEREG(OneWirePin) (&(digitalPinToPort(OneWirePin)->PIO_PER)) // //
- #define PIN_TO_BITMASK(OneWirePin) (digitalPinToBitMask(OneWirePin)) // //
- #define IO_REG_TYPE uint32_t // //
- #define IO_REG_ASM // //
- #define DIRECT_READ(base, mask) (((*((base)+15)) & (mask)) ? 1 : 0) // //
- #define DIRECT_MODE_INPUT(base, mask) ((*((base)+5)) = (mask)) // //
- #define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+4)) = (mask)) // //
- #define DIRECT_WRITE_LOW(base, mask) ((*((base)+13)) = (mask)) // //
- #define DIRECT_WRITE_HIGH(base, mask) ((*((base)+12)) = (mask)) // //
- #ifndef PROGMEM // //
- #define PROGMEM // //
- #endif // //
- #ifndef pgm_read_byte // //
- #define pgm_read_byte(addr) (*(const uint8_t *)(addr)) // //
- #endif // //
-#elif defined(__PIC32MX__) // //
- #define PIN_TO_BASEREG(OneWirePin) (portModeRegister(digitalPinToPort(OneWirePin)))// //
- #define PIN_TO_BITMASK(OneWirePin) (digitalPinToBitMask(OneWirePin)) // //
- #define IO_REG_TYPE uint32_t // //
- #define IO_REG_ASM // //
- #define DIRECT_READ(base, mask) (((*(base+4)) & (mask)) ? 1 : 0) // PORTX + 0x10 //
- #define DIRECT_MODE_INPUT(base, mask) ((*(base+2)) = (mask)) // TRISXSET + 0x08 //
- #define DIRECT_MODE_OUTPUT(base, mask) ((*(base+1)) = (mask)) // TRISXCLR + 0x04 //
- #define DIRECT_WRITE_LOW(base, mask) ((*(base+8+1)) = (mask)) // LATXCLR + 0x24 //
- #define DIRECT_WRITE_HIGH(base, mask) ((*(base+8+2)) = (mask)) // LATXSET + 0x28 //
-#else // //
- #error "Please define I/O register types here" // //
-#endif // //
-#ifndef DSFamily_h // Guard code definition //
- #define DSFamily_h // Define the name inside guard code//
- class DSFamily_Class { // Class definition //
- public: // Publicly visible methods //
- DSFamily_Class(const uint8_t OneWirePin, const uint8_t ReserveRom = 0 );// Class Constructor //
- ~DSFamily_Class(); // Class destructor //
- uint8_t ThermometersFound = 0; // Number of Devices discovered //
- uint16_t ConversionMillis; // Current conversion milliseconds //
- bool Parasitic = true; // If one or more parasitic devices //
- uint8_t ScanForDevices (); // Scan/rescan the 1-Wire microLAN //
- int16_t ReadDeviceTemp (const uint8_t deviceNumber, // Return the temperature //
- const bool raw=false); // optionally using the raw value //
- void DeviceStartConvert (const uint8_t deviceNumber=UINT8_MAX, // Start conversion on device //
- const bool WaitSwitch=false); // optionally wait for it to finish //
- void Calibrate (const uint8_t iterations=30, // Calibrate thermometers to read //
- const int16_t CalTemp=INT16_MAX); // identically //
- int8_t GetDeviceCalibration(const uint8_t deviceNumber); // Get the device's calibration //
- void SetDeviceCalibration(const uint8_t deviceNumber, // Set calibration bytes 1 & 2 //
- const int8_t offset); // //
- int16_t MinTemperature (const uint8_t skipDeviceNumber=UINT8_MAX);// Min of devices, optional skip //
- int16_t MaxTemperature (const uint8_t skipDeviceNumber=UINT8_MAX);// Max of devices, optional skip //
- int16_t AvgTemperature (const uint8_t skipDeviceNumber=UINT8_MAX);// Avg of devices, optional skip //
- float StdDevTemperature (const uint8_t skipDeviceNumber=UINT8_MAX);// Standard deviation, optional skip//
- void SetDeviceResolution (const uint8_t deviceNumber,uint8_t res); // Set resolution 9,10,11 or 12 bits//
- uint8_t GetDeviceResolution (const uint8_t deviceNumber); // Retrieve the device resolution //
- void GetDeviceROM (const uint8_t deviceNumber, // Return the physical ROM values //
- uint8_t ROMBuffer[8]); // //
- uint8_t crc8 (const uint8_t *addr, uint8_t len); // Compute 1-Wire 8bit CRC //
- private: // Private variables and methods //
- boolean Read1WireScratchpad (const uint8_t deviceNumber,uint8_t bf[9]);// Read device's scratchpad contents//
- void SelectDevice (const uint8_t deviceNumber); // Reset 1-Wire & select device //
- void ParasiticWait(); // Wait for conversion if parasitic //
- uint8_t _MaxThermometers; // Devices fit (EEPROM-ReserveRom) //
- uint32_t _ConvStartTime; // Conversion start time //
- bool _LastCommandWasConvert=false; // Unset when other commands issued //
- IO_REG_TYPE bitmask; // //
- volatile IO_REG_TYPE *baseReg; // //
- unsigned char ROM_NO[8]; // global search state //
- uint8_t LastDiscrepancy; // //
- uint8_t LastFamilyDiscrepancy; // //
- uint8_t LastDeviceFlag; // //
- void reset_search(); // 1-Wire reset search status //
- uint8_t reset(void); // Reset the 1-Wire microLAN state //
- void write_bit(uint8_t v); // Write 1 bit on 1-Wire microLAN //
- uint8_t read_bit(void); // Read 1 bit from 1-Wire microLAN //
- void write_byte(uint8_t v, uint8_t power = 0 ); // Write a byte to 1-Wire microLAN //
- uint8_t read_byte(); // Read a byte from 1-Wire microLAN //
- void select(const uint8_t rom[8]); // Select a give 1-Wire device //
- uint8_t search(uint8_t *newAddr); // Search 1-Wire for next device //
- }; // of DSFamily class definition // //
-#endif //----------------------------------//
+ #define PIN_TO_BASEREG(OneWirePin) (&(digitalPinToPort(OneWirePin)->PIO_PER))
+ #define PIN_TO_BITMASK(OneWirePin) (digitalPinToBitMask(OneWirePin))
+ #define IO_REG_TYPE uint32_t
+ #define IO_REG_ASM
+ #define DIRECT_READ(base, mask) (((*((base)+15)) & (mask)) ? 1 : 0)
+ #define DIRECT_MODE_INPUT(base, mask) ((*((base)+5)) = (mask))
+ #define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+4)) = (mask))
+ #define DIRECT_WRITE_LOW(base, mask) ((*((base)+13)) = (mask))
+ #define DIRECT_WRITE_HIGH(base, mask) ((*((base)+12)) = (mask))
+ #ifndef PROGMEM
+ #define PROGMEM
+ #endif
+ #ifndef pgm_read_byte
+ #define pgm_read_byte(addr) (*(const uint8_t *)(addr))
+ #endif
+#elif defined(__PIC32MX__)
+ #define PIN_TO_BASEREG(OneWirePin) (portModeRegister(digitalPinToPort(OneWirePin)))
+ #define PIN_TO_BITMASK(OneWirePin) (digitalPinToBitMask(OneWirePin))
+ #define IO_REG_TYPE uint32_t
+ #define IO_REG_ASM
+ #define DIRECT_READ(base, mask) (((*(base+4)) & (mask)) ? 1 : 0) // PORTX + 0x10
+ #define DIRECT_MODE_INPUT(base, mask) ((*(base+2)) = (mask)) // TRISXSET + 0x08
+ #define DIRECT_MODE_OUTPUT(base, mask) ((*(base+1)) = (mask)) // TRISXCLR + 0x04
+ #define DIRECT_WRITE_LOW(base, mask) ((*(base+8+1)) = (mask)) // LATXCLR + 0x24
+ #define DIRECT_WRITE_HIGH(base, mask) ((*(base+8+2)) = (mask)) // LATXSET + 0x28
+#else
+ #error "Please define I/O register types here"
+#endif
+#ifndef DSFamily_h
+ /** @brief Guard code to prevent multiple definitions */
+ #define DSFamily_h
+/*!
+* @class DSFamily_Class
+* @brief Access the available DS-Family devices on the 1-Wire bus
+*/ class DSFamily_Class
+ {
+ public:
+ DSFamily_Class(const uint8_t OneWirePin, const uint8_t ReserveRom = 0 );
+ ~DSFamily_Class();
+ uint16_t ConversionMillis; ///< Current conversion milliseconds
+ uint8_t ThermometersFound = 0; ///< Number of Devices discovered
+ bool Parasitic = true; ///< One or more parasitic devices present
+
+ uint8_t ScanForDevices ();
+ int16_t ReadDeviceTemp (const uint8_t deviceNumber, const bool raw=false);
+ void DeviceStartConvert (const uint8_t deviceNumber=UINT8_MAX, const bool WaitSwitch=false);
+ void Calibrate (const uint8_t iterations=30, const int16_t CalTemp=INT16_MAX);
+ int8_t GetDeviceCalibration(const uint8_t deviceNumber);
+ void SetDeviceCalibration(const uint8_t deviceNumber, const int8_t offset);
+ int16_t MinTemperature (const uint8_t skipDeviceNumber=UINT8_MAX);
+ int16_t MaxTemperature (const uint8_t skipDeviceNumber=UINT8_MAX);
+ int16_t AvgTemperature (const uint8_t skipDeviceNumber=UINT8_MAX);
+ float StdDevTemperature (const uint8_t skipDeviceNumber=UINT8_MAX);
+ void SetDeviceResolution (const uint8_t deviceNumber, uint8_t resolution);
+ uint8_t GetDeviceResolution (const uint8_t deviceNumber);
+ void GetDeviceROM (const uint8_t deviceNumber, uint8_t ROMBuffer[8]);
+ uint8_t crc8 (const uint8_t *addr, uint8_t len);
+ private:
+ uint8_t _MaxThermometers; ///< Number of devices found/stord
+ uint32_t _ConvStartTime; ///< Conversion start time
+ bool _LastCommandWasConvert=false; ///< Unset when other commands issued
+ IO_REG_TYPE bitmask; ///< Bitmask for 1-Wire IO
+ volatile IO_REG_TYPE *baseReg; ///< Base register
+ unsigned char ROM_NO[8]; ///< global search state array
+ uint8_t LastDiscrepancy; ///< 1-Wire internal value
+ uint8_t LastFamilyDiscrepancy; ///< 1-Wire internal value
+ uint8_t LastDeviceFlag; ///< 1-Wire internal value
+
+ boolean Read1WireScratchpad(const uint8_t deviceNumber, uint8_t bf[9]);
+ void SelectDevice(const uint8_t deviceNumber);
+ void ParasiticWait();
+ void reset_search();
+ uint8_t reset(void);
+ void write_bit(uint8_t v);
+ uint8_t read_bit(void);
+ void write_byte(uint8_t v, uint8_t power = 0 );
+ uint8_t read_byte();
+ void select(const uint8_t rom[8]);
+ uint8_t search(uint8_t *newAddr);
+ }; // of DSFamily class definition
+#endif