/*
 * Copyright (c) 2016 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <device.h>
#include <gpio.h>
#include <misc/byteorder.h>
#include <misc/util.h>
#include <sensor.h>
#include <string.h>
#include <zephyr.h>
#include <logging/log.h>

#include "dht.h"

#define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL
LOG_MODULE_REGISTER(DHT);

/**
 * @brief Measure duration of signal send by sensor
 *
 * @param drv_data Pointer to the driver data structure
 * @param signal_val Value of signal being measured
 *
 * @return duration in usec of signal being measured,
 *         -1 if duration exceeds DHT_SIGNAL_MAX_WAIT_DURATION
 */
static s8_t dht_measure_signal_duration(struct dht_data *drv_data,
					  u32_t signal_val)
{
	u32_t val;
	u32_t elapsed_cycles;
	u32_t max_wait_cycles = (u32_t)(
		(u64_t)DHT_SIGNAL_MAX_WAIT_DURATION *
		(u64_t)sys_clock_hw_cycles_per_sec() /
		(u64_t)USEC_PER_SEC
	);
	u32_t start_cycles = k_cycle_get_32();

	do {
		gpio_pin_read(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM, &val);
		elapsed_cycles = k_cycle_get_32() - start_cycles;

		if (elapsed_cycles > max_wait_cycles) {
			return -1;
		}
	} while (val == signal_val);

	return (u64_t)elapsed_cycles *
	       (u64_t)USEC_PER_SEC /
	       (u64_t)sys_clock_hw_cycles_per_sec();
}

static int dht_sample_fetch(struct device *dev, enum sensor_channel chan)
{
	struct dht_data *drv_data = dev->driver_data;
	int ret = 0;
	s8_t signal_duration[DHT_DATA_BITS_NUM];
	s8_t max_duration, min_duration, avg_duration;
	u8_t buf[5];
	unsigned int i, j;

	__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL);

	/* send start signal */
	gpio_pin_write(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM, 0);

	k_busy_wait(DHT_START_SIGNAL_DURATION);

	gpio_pin_write(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM, 1);

	/* switch to DIR_IN to read sensor signals */
	gpio_pin_configure(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM,
			   GPIO_DIR_IN);

	/* wait for sensor response */
	if (dht_measure_signal_duration(drv_data, 1) == -1) {
		ret = -EIO;
		goto cleanup;
	}

	/* read sensor response */
	if (dht_measure_signal_duration(drv_data, 0) == -1) {
		ret = -EIO;
		goto cleanup;
	}

	/* wait for sensor data */
	if (dht_measure_signal_duration(drv_data, 1) == -1) {
		ret = -EIO;
		goto cleanup;
	}

	/* read sensor data */
	for (i = 0U; i < DHT_DATA_BITS_NUM; i++) {
		/* LOW signal to indicate a new bit */
		if (dht_measure_signal_duration(drv_data, 0) == -1) {
			ret = -EIO;
			goto cleanup;
		}

		/* HIGH signal duration indicates bit value */
		signal_duration[i] = dht_measure_signal_duration(drv_data, 1);
		if (signal_duration[i] == -1) {
			ret = -EIO;
			goto cleanup;
		}
	}

	/*
	 * the datasheet says 20-40us HIGH signal duration for a 0 bit and
	 * 80us for a 1 bit; however, since dht_measure_signal_duration is
	 * not very precise, compute the threshold for deciding between a
	 * 0 bit and a 1 bit as the average between the minimum and maximum
	 * if the durations stored in signal_duration
	 */
	min_duration = signal_duration[0];
	max_duration = signal_duration[0];
	for (i = 1U; i < DHT_DATA_BITS_NUM; i++) {
		if (min_duration > signal_duration[i]) {
			min_duration = signal_duration[i];
		}
		if (max_duration < signal_duration[i]) {
			max_duration = signal_duration[i];
		}
	}
	avg_duration = ((s16_t)min_duration + (s16_t)max_duration) / 2;

	/* store bits in buf */
	j = 0U;
	(void)memset(buf, 0, sizeof(buf));
	for (i = 0U; i < DHT_DATA_BITS_NUM; i++) {
		if (signal_duration[i] >= avg_duration) {
			buf[j] = (buf[j] << 1) | 1;
		} else {
			buf[j] = buf[j] << 1;
		}

		if (i % 8 == 7U) {
			j++;
		}
	}

	/* verify checksum */
	if (((buf[0] + buf[1] + buf[2] + buf[3]) & 0xFF) != buf[4]) {
		LOG_DBG("Invalid checksum in fetched sample");
		ret = -EIO;
	} else {
		memcpy(drv_data->sample, buf, 4);
	}

cleanup:
	/* switch to DIR_OUT and leave pin to HIGH until next fetch */
	gpio_pin_configure(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM,
			   GPIO_DIR_OUT);
	gpio_pin_write(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM, 1);

	return ret;
}

static int dht_channel_get(struct device *dev,
			   enum sensor_channel chan,
			   struct sensor_value *val)
{
	struct dht_data *drv_data = dev->driver_data;

	__ASSERT_NO_MSG(chan == SENSOR_CHAN_AMBIENT_TEMP || chan == SENSOR_CHAN_HUMIDITY);

	/* see data calculation example from datasheet */
#if defined(CONFIG_DHT_CHIP_DHT11)
	/* use only integral data byte */
	if (chan == SENSOR_CHAN_HUMIDITY) {
		val->val1 = drv_data->sample[0];
		val->val2 = 0;
	} else { /* chan == SENSOR_CHAN_AMBIENT_TEMP */
		val->val1 = drv_data->sample[2];
		val->val2 = 0;
	}
#elif defined(CONFIG_DHT_CHIP_DHT22)
	/*
	 * use both integral and decimal data bytes; resulted 16bit data has
	 * a resolution of 0.1 units
	 */
	s16_t raw_val, sign;

	if (chan == SENSOR_CHAN_HUMIDITY) {
		raw_val = (drv_data->sample[0] << 8) | drv_data->sample[1];
		val->val1 = raw_val / 10;
		val->val2 = (raw_val % 10) * 100000;
	} else { /* chan == SENSOR_CHAN_AMBIENT_TEMP */
		raw_val = (drv_data->sample[2] << 8) | drv_data->sample[3];

		sign = raw_val & 0x8000;
		raw_val = raw_val & ~0x8000;

		val->val1 = raw_val / 10;
		val->val2 = (raw_val % 10) * 100000;

		/* handle negative value */
		if (sign) {
			val->val1 = -val->val1;
			val->val2 = -val->val2;
		}
	}
#endif

	return 0;
}

static const struct sensor_driver_api dht_api = {
	.sample_fetch = &dht_sample_fetch,
	.channel_get = &dht_channel_get,
};

static int dht_init(struct device *dev)
{
	struct dht_data *drv_data = dev->driver_data;

	drv_data->gpio = device_get_binding(CONFIG_DHT_GPIO_DEV_NAME);
	if (drv_data->gpio == NULL) {
		LOG_ERR("Failed to get GPIO device.");
		return -EINVAL;
	}

	gpio_pin_configure(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM,
			   GPIO_DIR_OUT);

	gpio_pin_write(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM, 1);

	return 0;
}

struct dht_data dht_data;

DEVICE_AND_API_INIT(dht_dev, CONFIG_DHT_NAME, &dht_init, &dht_data,
		    NULL, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &dht_api);
