// set resolution of a device to 9, 10, 11, or 12 bits
// if new resolution is out of range, 9 bits is used. 
bool DallasTemperature::setResolution(uint8_t* deviceAddress, uint8_t newResolution)
{
  ScratchPad scratchPad;
  if (isConnected(deviceAddress, scratchPad))
  {
    // DS18S20 has a fixed 9-bit resolution
    if (deviceAddress[0] != DS18S20MODEL)
    {
      switch (newResolution)
      {
        case 12:
          scratchPad[CONFIGURATION] = TEMP_12_BIT;
          break;
        case 11:
          scratchPad[CONFIGURATION] = TEMP_11_BIT;
          break;
        case 10:
          scratchPad[CONFIGURATION] = TEMP_10_BIT;
          break;
        case 9:
        default:
          scratchPad[CONFIGURATION] = TEMP_9_BIT;
          break;
      }
      writeScratchPad(deviceAddress, scratchPad);
    }
	return true;  // new value set
  }
  return false;
}
bool DallasTemperature::setResolution(const uint8_t* deviceAddress, uint8_t newResolution) {
    ScratchPad scratchPad;
    if (readScratchPadCRC(deviceAddress, scratchPad)) {
        // DS18S20 has a fixed 9-bit resolution
        if (!isDS18S20Model(deviceAddress)) {
            uint8_t resolution;
#if REQUIRESONLY12BITCONVERSION
            resolution = TEMP_12_BIT;
#else						
            switch (newResolution) {
                case 12:
                    resolution = TEMP_12_BIT;
                    break;
                case 11:
                    resolution = TEMP_11_BIT;
                    break;
                case 10:
                    resolution = TEMP_10_BIT;
                    break;
                case 9:
                default:
                    resolution = TEMP_9_BIT;
                    break;
            }
#endif			
            scratchPad[CONFIGURATION] = resolution;
            writeScratchPad(deviceAddress, scratchPad, false);
        }
        return true; // new value set
    }
    return false;
}
// note if device is not connected it will fail writing the data.
void DallasTemperature::setUserData(const uint8_t* deviceAddress, int16_t data)
{
    ScratchPad scratchPad;
    if (isConnected(deviceAddress, scratchPad))
    {
        scratchPad[HIGH_ALARM_TEMP] = data >> 8;
        scratchPad[LOW_ALARM_TEMP] = data & 255;
        writeScratchPad(deviceAddress, scratchPad);
    }
}
void DallasTemperature::setLowAlarmTemp(const uint8_t* deviceAddress, char celsius) {
    // make sure the alarm temperature is within the device's range
    if (celsius > 125) celsius = 125;
    else if (celsius < -55) celsius = -55;

    ScratchPad scratchPad;
    if (readScratchPadCRC(deviceAddress, scratchPad)) {
        scratchPad[LOW_ALARM_TEMP] = (uint8_t) celsius;
        writeScratchPad(deviceAddress, scratchPad, true);
    }
}
bool DallasTemperature::initConnection(const uint8_t* deviceAddress) {
#if REQUIRESRESETDETECTION
    ScratchPad scratchPad;
    bool writeSettings = false;

    if (isParasitePowered(deviceAddress)) {
        return false;
    }
    // Reload settings from EEPROM so we can skip writing EEPROM if the values are already set
    recallScratchpad(deviceAddress);
    if (!readScratchPadCRC(deviceAddress, scratchPad)) {
        return false;
    }

#if REQUIRESONLY12BITCONVERSION		
    if(scratchPad[CONFIGURATION] != TEMP_12_BIT){
        scratchPad[CONFIGURATION] = TEMP_12_BIT;
        writeSettings = true;
    }
#endif

    // Make sure that HIGH_ALARM_TEMP is set to zero in EEPROM
    // This value will be loaded on power on
    if (scratchPad[HIGH_ALARM_TEMP]) { // conditional to avoid wear on eeprom. 			
        scratchPad[HIGH_ALARM_TEMP] = 0;
        writeSettings = true;
    }

    if (writeSettings){
        writeScratchPad(deviceAddress, scratchPad, true); // save settings to eeprom
    }
    // Write HIGH_ALARM_TEMP again, but don't save to EEPROM, so that it reverts to 0 on reset
    // from this point on, if we read a scratchpad with a 0 value in HIGH_ALARM (detectedReset() returns true)
    // it means the device has reset or the previous write of the scratchpad above was unsuccessful.
    // Either way, initConnection() should be called again
    scratchPad[HIGH_ALARM_TEMP] = 1;
    writeScratchPad(deviceAddress, scratchPad, false); 
#endif
    return true;

}
// sets the high alarm temperature for a device in degrees celsius
// accepts a float, but the alarm resolution will ignore anything
// after a decimal point.  valid range is -55C - 125C
void DallasTemperature::setHighAlarmTemp(uint8_t* deviceAddress, char celsius)
{
  // make sure the alarm temperature is within the device's range
  if (celsius > 125) celsius = 125;
  else if (celsius < -55) celsius = -55;

  ScratchPad scratchPad;
  if (isConnected(deviceAddress, scratchPad))
  {
    scratchPad[HIGH_ALARM_TEMP] = (uint8_t)celsius;
    writeScratchPad(deviceAddress, scratchPad);
  }
}
// note if device is not connected it will fail writing the data.
void DallasTemperature::setUserData(const uint8_t* deviceAddress, int16_t data)
{
    // return when stored value == new value
    if(getUserData(deviceAddress) == data) return;

    ScratchPad scratchPad;
    if (isConnected(deviceAddress, scratchPad))
    {
        scratchPad[HIGH_ALARM_TEMP] = data >> 8;
        scratchPad[LOW_ALARM_TEMP] = data & 255;
        writeScratchPad(deviceAddress, scratchPad);
    }
}
// set resolution of a device to 9, 10, 11, or 12 bits
// if new resolution is out of range, 9 bits is used.
bool DallasTemperature::setResolution(const uint8_t* deviceAddress, uint8_t newResolution, bool skipGlobalBitResolutionCalculation){

	// ensure same behavior as setResolution(uint8_t newResolution)
	newResolution = constrain(newResolution, 9, 12);
			
    // return when stored value == new value
    if(getResolution(deviceAddress) == newResolution) return true;

    ScratchPad scratchPad;
    if (isConnected(deviceAddress, scratchPad)){

        // DS1820 and DS18S20 have no resolution configuration register
        if (deviceAddress[0] != DS18S20MODEL){

            switch (newResolution){
            case 12:
                scratchPad[CONFIGURATION] = TEMP_12_BIT;
                break;
            case 11:
                scratchPad[CONFIGURATION] = TEMP_11_BIT;
                break;
            case 10:
                scratchPad[CONFIGURATION] = TEMP_10_BIT;
                break;
            case 9:
            default:
                scratchPad[CONFIGURATION] = TEMP_9_BIT;
                break;
            }
            writeScratchPad(deviceAddress, scratchPad);

            // without calculation we can always set it to max
			bitResolution = max(bitResolution, newResolution);
			
			if(!skipGlobalBitResolutionCalculation && (bitResolution > newResolution)){
				bitResolution = newResolution;
				DeviceAddress deviceAddr;
				for (int i=0; i<devices; i++)
				{
					getAddress(deviceAddr, i);
					bitResolution = max(bitResolution, getResolution(deviceAddr));
				}
			}
        }
        return true;  // new value set
    }

    return false;

}
// sets the low alarm temperature for a device in degrees Celsius
// accepts a float, but the alarm resolution will ignore anything
// after a decimal point.  valid range is -55C - 125C
void DallasTemperature::setLowAlarmTemp(const uint8_t* deviceAddress, char celsius){
    
    // return when stored value == new value
    if(getLowAlarmTemp(deviceAddress) == celsius) return;

    // make sure the alarm temperature is within the device's range
    if (celsius > 125) celsius = 125;
    else if (celsius < -55) celsius = -55;

    ScratchPad scratchPad;
    if (isConnected(deviceAddress, scratchPad)){
        scratchPad[LOW_ALARM_TEMP] = (uint8_t)celsius;
        writeScratchPad(deviceAddress, scratchPad);
    }

}