#include <dht.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

dht DHT;
#define DHT22_PIN 5
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

// Initialize the OLED display with I2C address 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

struct {
  uint32_t total;
  uint32_t ok;
  uint32_t crc_error;
  uint32_t time_out;
  uint32_t connect;
  uint32_t ack_l;
  uint32_t ack_h;
  uint32_t unknown;
} stat = { 0, 0, 0, 0, 0, 0, 0, 0};

void setup() {
  Serial.begin(115200);
  Serial.println("dht22_test.ino");
  Serial.print("LIBRARY VERSION: ");
  Serial.println(DHT_LIB_VERSION);
  Serial.println();

  // Initialize the OLED display
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.print("Initializing DHT22");
  display.display();
  delay(2000);
}

void loop() {
  uint32_t start = micros();
  int chk = DHT.read22(DHT22_PIN);
  uint32_t stop = micros();

  stat.total++;
  String statusMessage;
  switch (chk) {
    case DHTLIB_OK:
      stat.ok++;
      statusMessage = "OK";
      break;
    case DHTLIB_ERROR_CHECKSUM:
      stat.crc_error++;
      statusMessage = "Checksum error";
      break;
    case DHTLIB_ERROR_TIMEOUT:
      stat.time_out++;
      statusMessage = "Time out error";
      break;
    case DHTLIB_ERROR_CONNECT:
      stat.connect++;
      statusMessage = "Connect error";
      break;
    case DHTLIB_ERROR_ACK_L:
      stat.ack_l++;
      statusMessage = "Ack Low error";
      break;
    case DHTLIB_ERROR_ACK_H:
      stat.ack_h++;
      statusMessage = "Ack High error";
      break;
    default:
      stat.unknown++;
      statusMessage = "Unknown error";
      break;
  }

  // Convert Celsius to Fahrenheit
  float tempF = DHT.temperature * 9.0 / 5.0 + 32.0;

  // Print the results to Serial
  Serial.print("DHT22, \t");
  Serial.print(statusMessage);
  Serial.print(",\t");
  Serial.print(DHT.humidity, 1);
  Serial.print(",\t");
  Serial.print(DHT.temperature, 1);
  Serial.print(" C, ");
  Serial.print(tempF, 1);
  Serial.print(" F, ");
  Serial.print(stop - start);
  Serial.println(" us");

  // Display results on OLED
  display.clearDisplay();
  display.setCursor(0, 0);
  display.print("Status: ");
  display.println(statusMessage);
  display.print("Humidity: ");
  display.print(DHT.humidity, 1);
  display.println(" %");
  display.print("Temp: ");
  display.print(DHT.temperature, 1);
  display.println(" C");
  display.print("      ");
  display.print(tempF, 1);
  display.println(" F");
  display.print("Time: ");
  display.print(stop - start);
  display.println(" us");
  display.display();

  delay(2000);
}