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

#include <device.h>
#include <i2c.h>
#include <gpio.h>
#include <kernel.h>
#include <sensor.h>
#include <misc/util.h>
#include <misc/__assert.h>
#include <logging/log.h>

#include "hdc1008.h"

#define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL
LOG_MODULE_REGISTER(HDC1008);

static void hdc1008_gpio_callback(struct device *dev,
				  struct gpio_callback *cb, u32_t pins)
{
	struct hdc1008_data *drv_data =
		CONTAINER_OF(cb, struct hdc1008_data, gpio_cb);

	ARG_UNUSED(pins);

	gpio_pin_disable_callback(dev, DT_TI_HDC1008_0_DRDY_GPIOS_PIN);
	k_sem_give(&drv_data->data_sem);
}

static int hdc1008_sample_fetch(struct device *dev, enum sensor_channel chan)
{
	struct hdc1008_data *drv_data = dev->driver_data;
	u8_t buf[4];

	__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL);

	gpio_pin_enable_callback(drv_data->gpio,
				 DT_TI_HDC1008_0_DRDY_GPIOS_PIN);

	buf[0] = HDC1008_REG_TEMP;
	if (i2c_write(drv_data->i2c, buf, 1,
		      DT_TI_HDC1008_0_BASE_ADDRESS) < 0) {
		LOG_DBG("Failed to write address pointer");
		return -EIO;
	}

	k_sem_take(&drv_data->data_sem, K_FOREVER);

	if (i2c_read(drv_data->i2c, buf, 4, DT_TI_HDC1008_0_BASE_ADDRESS) < 0) {
		LOG_DBG("Failed to read sample data");
		return -EIO;
	}

	drv_data->t_sample = (buf[0] << 8) + buf[1];
	drv_data->rh_sample = (buf[2] << 8) + buf[3];

	return 0;
}


static int hdc1008_channel_get(struct device *dev,
			       enum sensor_channel chan,
			       struct sensor_value *val)
{
	struct hdc1008_data *drv_data = dev->driver_data;
	u64_t tmp;

	/*
	 * See datasheet "Temperature Register" and "Humidity
	 * Register" sections for more details on processing
	 * sample data.
	 */
	if (chan == SENSOR_CHAN_AMBIENT_TEMP) {
		/* val = -40 + 165 * sample / 2^16 */
		tmp = 165 * (u64_t)drv_data->t_sample;
		val->val1 = (s32_t)(tmp >> 16) - 40;
		val->val2 = (1000000 * (tmp & 0xFFFF)) >> 16;
	} else if (chan == SENSOR_CHAN_HUMIDITY) {
		/* val = 100 * sample / 2^16 */
		u32_t tmp2;
		tmp2 = 100 * (u32_t)drv_data->rh_sample;
		val->val1 = tmp2 >> 16;
		/* x * 1000000 / 65536 == x * 15625 / 1024 */
		val->val2 = (15625 * (tmp2 & 0xFFFF)) >> 10;
	} else {
		return -ENOTSUP;
	}

	return 0;
}

static const struct sensor_driver_api hdc1008_driver_api = {
	.sample_fetch = hdc1008_sample_fetch,
	.channel_get = hdc1008_channel_get,
};

static u16_t read16(struct device *dev, u8_t a, u8_t d)
{
	u8_t buf[2];
	if (i2c_burst_read(dev, a, d, (u8_t *)buf, 2) < 0) {
		LOG_ERR("Error reading register.");
	}
	return (buf[0] << 8 | buf[1]);
}

static int hdc1008_init(struct device *dev)
{
	struct hdc1008_data *drv_data = dev->driver_data;

	drv_data->i2c = device_get_binding(DT_TI_HDC1008_0_BUS_NAME);

	if (drv_data->i2c == NULL) {
		LOG_DBG("Failed to get pointer to %s device!",
			DT_TI_HDC1008_0_BUS_NAME);
		return -EINVAL;
	}

	if (read16(drv_data->i2c, DT_TI_HDC1008_0_BASE_ADDRESS,
		   HDC1008_REG_MANUFID) != HDC1008_MANUFID) {
		LOG_ERR("Failed to get correct manufacturer ID");
		return -EINVAL;
	}
	if (read16(drv_data->i2c, DT_TI_HDC1008_0_BASE_ADDRESS,
		   HDC1008_REG_DEVICEID) != HDC1008_DEVICEID) {
		LOG_ERR("Failed to get correct device ID");
		return -EINVAL;
	}

	k_sem_init(&drv_data->data_sem, 0, UINT_MAX);

	/* setup data ready gpio interrupt */
	drv_data->gpio = device_get_binding(
				DT_TI_HDC1008_0_DRDY_GPIOS_CONTROLLER);
	if (drv_data->gpio == NULL) {
		LOG_DBG("Failed to get pointer to %s device",
			 DT_TI_HDC1008_0_DRDY_GPIOS_CONTROLLER);
		return -EINVAL;
	}

	gpio_pin_configure(drv_data->gpio, DT_TI_HDC1008_0_DRDY_GPIOS_PIN,
			   GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE |
#if defined(DT_TI_HDC1008_0_DRDY_GPIOS_FLAGS)
			   DT_TI_HDC1008_0_DRDY_GPIOS_FLAGS |
#endif
			   GPIO_INT_ACTIVE_LOW | GPIO_INT_DEBOUNCE);

	gpio_init_callback(&drv_data->gpio_cb,
			   hdc1008_gpio_callback,
			   BIT(DT_TI_HDC1008_0_DRDY_GPIOS_PIN));

	if (gpio_add_callback(drv_data->gpio, &drv_data->gpio_cb) < 0) {
		LOG_DBG("Failed to set GPIO callback");
		return -EIO;
	}

	return 0;
}

static struct hdc1008_data hdc1008_data;

DEVICE_AND_API_INIT(hdc1008, DT_TI_HDC1008_0_LABEL, hdc1008_init, &hdc1008_data,
		    NULL, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,
		    &hdc1008_driver_api);
