//
//    FILE: dhtnew_pulse_diag.ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.1
// PURPOSE: DHTNEW library pulse measurement tool - diagnostics
//     URL: https://github.com/RobTillaart/DHTNew
//
// HISTORY:
// 0.1.0    2020-08-15 initial version
// 0.1.1    2020-09-23 commented noInterrupts as it corrupts timing on AVR.

//
// DHT PIN layout from left to right
// =================================
// FRONT : DESCRIPTION
// pin 1 : VCC
// pin 2 : DATA
// pin 3 : Not Connected
// pin 4 : GND

#include "Arduino.h"

#define DHTLIB_DHT11_WAKEUP        18
#define DHTLIB_DHT_WAKEUP          1

uint8_t   _dataPin = 16;
uint8_t   _wakeupDelay = DHTLIB_DHT_WAKEUP;

uint16_t  count = 0;
uint32_t  times[100], t = 0;
uint8_t   idx = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println("dhtnew_pulse_diag.ino");
  Serial.println();

  // default should be HIGH
  pinMode(_dataPin, OUTPUT);
  digitalWrite(_dataPin, HIGH);
}

void loop()
{
  measure();
  dump();
  delay(5000);
}

void dump()
{
  int i = 1;
  Serial.println();
  Serial.print("RUN:\t"); Serial.println(count);
  Serial.print("IDX:\t"); Serial.println(idx);

  Serial.println("WAKEUP");
  for (int n = 0; n < 6; n++)
  {
    Serial.print("\t");
    Serial.print(times[i++]);
  }
  Serial.println();

  Serial.println("HUM");
  for (int n = 0; n < 32; n++)
  {
    Serial.print("\t");
    Serial.print(times[i++]);
    if ((n & 15) == 15) Serial.println();
  }
  Serial.println();

  Serial.println("TEMP");
  for (int n = 0; n < 32; n++)
  {
    Serial.print("\t");
    Serial.print(times[i++]);
    if ((n & 15) == 15) Serial.println();
  }
  Serial.println();

  Serial.println("CRC");
  for (int n = 0; n < 16; n++)
  {
    Serial.print("\t");
    Serial.print(times[i++]);
    if ((n & 7) == 7) Serial.println();
  }
  Serial.println();

  Serial.println("BYE");
  for (int n = 0; n < 2; n++)
  {
    Serial.print("\t");
    Serial.print(times[i++]);
  }
  Serial.println();
  Serial.println();
}


void measure()
{
  count++;
  yield(); // handle pending interrupts

  // reset measurements table
  idx = 0;
  t = micros();
  for (int i = 0; i < 100; i++) times[i] = 0;

  times[idx++] = micros();
  // REQUEST SAMPLE - SEND WAKEUP TO SENSOR
  pinMode(_dataPin, OUTPUT);
  digitalWrite(_dataPin, LOW);
  // add 10% extra for timing inaccuracies in sensor.
  delayMicroseconds(_wakeupDelay * 1100UL);


  times[idx++] = micros();
  // HOST GIVES CONTROL TO SENSOR
  pinMode(_dataPin, INPUT_PULLUP);

  // DISABLE INTERRUPTS when clock in the bits
  // noInterrupts();      // gives problems on AVR


  times[idx++] = micros();
  // SENSOR PULLS LOW after 20-40 us  => if stays HIGH ==> device not ready
  while (digitalRead(_dataPin) == HIGH);


  times[idx++] = micros();
  // SENSOR STAYS LOW for ~80 us => or TIMEOUT
  while (digitalRead(_dataPin) == LOW);


  times[idx++] = micros();
  // SENSOR STAYS HIGH for ~80 us => or TIMEOUT
  while (digitalRead(_dataPin) == HIGH);
  times[idx++] = micros();


  // SENSOR HAS NOW SEND ACKNOWLEDGE ON WAKEUP
  // NOW IT SENDS THE BITS

  // READ THE OUTPUT - 40 BITS => 5 BYTES
  for (uint8_t i = 40; i != 0; i--)
  {
    times[idx++] = micros();
    // EACH BIT START WITH ~50 us LOW
    while (digitalRead(_dataPin) == LOW);

    times[idx++] = micros();
    // DURATION OF HIGH DETERMINES 0 or 1
    // 26-28 us ==> 0
    //    70 us ==> 1
    while (digitalRead(_dataPin) == HIGH);
  }


  times[idx++] = micros();
  // After 40 bits the sensor pulls the line LOW for 50 us
  // TODO: should we wait?
  while (digitalRead(_dataPin) == LOW);

  times[idx++] = micros();
  times[idx++] = micros();

  for (int n = 100; n > 0; n--)
  {
    times[n] -= times[n - 1];
  }
}


// -- END OF FILE --