#include <DallasTemperature.h>
#include <OneWire.h>

#define ONE_WIRE_BUS 13

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// arrays to hold device address
DeviceAddress insideThermometer;


void setup() {

  Serial.begin(115200);
  delay(100);
  
  Serial.print("Locating devices...");
  sensors.begin();
  Serial.print("Found ");
  Serial.print(sensors.getDeviceCount(), DEC);
  Serial.println(" devices.");

  // report parasite power requirements
  Serial.print("Parasite power is: "); 
  if (sensors.isParasitePowerMode()) Serial.println("ON");
  else Serial.println("OFF");
  
  if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0"); 
  
  // show the addresses we found on the bus
  Serial.print("Device 0 Address: ");
  printAddress(insideThermometer);
  Serial.println();

  // set the resolution to 12 bit (Each Dallas/Maxim device is capable of several different resolutions)
  sensors.setResolution(insideThermometer, 9);
 
  Serial.print("Device 0 Resolution: ");
  Serial.print(sensors.getResolution(insideThermometer), DEC); 
  Serial.println();

  // enable async mode. Take care you put enough time between calls to "requestTemperatures"
  sensors.setWaitForConversion(false); 

}

uint32_t inline IRAM_ATTR cycles()
{
    uint32_t ccount;
    __asm__ __volatile__ ( "rsr     %0, ccount" : "=a" (ccount) );
    return ccount;
}


// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress)
{

  uint32_t t00, t01;

  t00 = cycles();
  float tempC = sensors.getTempC(deviceAddress);
  t01 = cycles();
  Serial.print("Temp C: ");
  Serial.print(tempC); Serial.print(" ");
  Serial.print("getTemp time [ms]: "); Serial.print((t01-t00-7) / 240000.0, 3); Serial.print(" ");
}


void loop(void)
{ 
  static uint32_t last_request = 0;

  uint32_t t00, t01;
  
  uint32_t now = millis();
  
  // check for wraparound, just in case...
  if (now < last_request)  {
    last_request = now;
  }
  
  // put some time between conversion requests
  if( (now - last_request) > 100) {
    Serial.print("Requesting temperatures...");

    t00 = cycles(); // Capture request time
    sensors.requestTemperatures(); // Send the command to get temperatures
    t01 = cycles();
    
    Serial.println("DONE");
    last_request = now;
  }
 
    
  printTemperature(insideThermometer); // Use a simple function to print out the data
  Serial.print("request time [ms]: "); Serial.print((t01-t00-7) / 240000.0, 3);
  Serial.println();

  // do other stuff here ;)
  delay(100);
}

// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}