/*
 * Copyright (c) 2016 Intel Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

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

#include "sensor_dht.h"

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

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

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

	return (uint64_t)elapsed_cycles *
	       (uint64_t)USEC_PER_SEC /
	       (uint64_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;
	int8_t signal_duration[DHT_DATA_BITS_NUM];
	int8_t max_duration, min_duration, avg_duration;
	uint8_t buf[5];
	unsigned int i, j;

	__ASSERT(chan == SENSOR_CHAN_ALL);

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

	sys_thread_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 = 0; 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 = 1; 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 = ((int16_t)min_duration + (int16_t)max_duration) / 2;

	/* store bits in buf */
	j = 0;
	memset(buf, 0, sizeof(buf));
	for (i = 0; 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 == 7) {
			j++;
		}
	}

	/* verify checksum */
	if (((buf[0] + buf[1] + buf[2] + buf[3]) & 0xFF) != buf[4]) {
		SYS_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(chan == SENSOR_CHAN_TEMP || chan == SENSOR_CHAN_HUMIDITY);

	val->type = SENSOR_VALUE_TYPE_INT_PLUS_MICRO;

	/* 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] * 1000;
		val->val2 = 0;
	} else { /* chan == SENSOR_CHAN_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
	 */
	int16_t raw_val, sign;

	if (chan == SENSOR_CHAN_HUMIDITY) {
		raw_val = (drv_data->sample[0] << 8) | drv_data->sample[1];
		val->val1 = raw_val * 100;
		val->val2 = 0;
	} else { /* chan == SENSOR_CHAN_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 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) {
		SYS_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);

	dev->driver_api = &dht_api;

	return 0;
}

struct dht_data dht_data;

DEVICE_INIT(dht_dev, CONFIG_DHT_NAME, &dht_init, &dht_data,
	    NULL, SECONDARY, CONFIG_DHT_INIT_PRIORITY);
