#include "DHT22.h"
#include <avr/io.h>
#include <stdbool.h>
#include <util/delay.h>

// Function to read data from the DHT22 sensor
int DHT22_Read(int *temperature, int *humidity) {
    // Set the data pin as output
    DDR |= (1 << DATAPIN);
    PORT |= (1 << DATAPIN); // Set the pin high, if not already pulled up

    _delay_ms(100);

    // Send start signal
    PORT &= ~(1 << DATAPIN); // Set the pin low
    _delay_us(500);          // Hold it for a while
    PORT |= (1 << DATAPIN);  // Set the pin high
    DDR &= ~(1 << DATAPIN);  // Data direction in

    _delay_us(20); // Wait for 40 microseconds

    // Sensor should have pulled low here
    if (PIN & (1 << DATAPIN))
        return -2;

    _delay_us(80); // Wait for 80 microseconds

    // Sensor should have pulled high here
    if (!(PIN & (1 << DATAPIN)))
        return -1;

    // Read data from the sensor
    uint8_t data[5]   = {0, 0, 0, 0, 0};
    uint8_t bitMask   = 0x80; // All zeroes with MSB high
    uint8_t byteIndex = 0;

    for (byteIndex = 0; byteIndex < 5; byteIndex++) {
        for (bitMask = 0x80; bitMask != 0; bitMask >>= 1) {
            // Wait for the data bit to go low
            while (!(PIN & (1 << PC0)));

            // Wait for the data bit to go high
            _delay_us(20);
            if (PIN & (1 << PC0))
                data[byteIndex] |= bitMask;

            // Wait for the data bit to go low (end of bit)
            while (PIN & (1 << PC0));
        }
    }

    // Verify checksum
    uint8_t checksum = data[0] + data[1] + data[2] + data[3];
    if (checksum != data[4])
        return -1;

    // Extract temperature and humidity
    *humidity    = ((data[0] << 8) | data[1]);
    *temperature = ((data[2] << 8) | data[3]);

    return 0;
}