/*
 * Copyright (c) 2021 Thomas Stranger
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT sensirion_shtcx

#include <zephyr/device.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/sys/__assert.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/crc.h>
#include <zephyr/logging/log.h>

#include "shtcx.h"

LOG_MODULE_REGISTER(SHTCX, CONFIG_SENSOR_LOG_LEVEL);

/* all cmds read temp first: cmd[MEASURE_MODE][Clock_stretching_enabled] */
static const uint16_t measure_cmd[2][2] = {
	{ 0x7866, 0x7CA2 },
	{ 0x609C, 0x6458 },
};

/* measure_wait_us[shtcx_chip][MEASURE_MODE] */
static const uint16_t measure_wait_us[2][2] = {
	/* shtc1: 14.4ms, 0.94ms */
	{ 14400, 940 }, /* shtc1 */
	/* shtc3: 12.1ms, 0.8ms */
	{ 1210, 800 }, /* shtc3 */
};

/*
 * CRC algorithm parameters were taken from the
 * "Checksum Calculation" section of the datasheet.
 */
static uint8_t shtcx_compute_crc(uint16_t value)
{
	uint8_t buf[2];

	sys_put_be16(value, buf);
	return crc8(buf, 2, 0x31, 0xFF, false);
}

/* val = -45 + 175 * sample / (2^16) */
static void shtcx_temperature_from_raw(uint16_t raw, struct sensor_value *val)
{
	int32_t tmp;

	tmp = (int32_t)raw * 175U - (45 << 16);
	val->val1 = tmp / 0x10000;
	/* x * 1.000.000 / 65.536 == x * 15625 / 2^10 */
	val->val2 = ((tmp % 0x10000) * 15625U) / 1024;
}

/* val = 100 * sample / (2^16) */
static void shtcx_humidity_from_raw(uint16_t raw, struct sensor_value *val)
{
	uint32_t tmp;

	tmp = (uint32_t)raw * 100U;
	val->val1 = tmp / 0x10000;
	/* x * 1.000.000 / 65.536 == x * 15625 / 1024 */
	val->val2 = (tmp % 0x10000) * 15625U / 1024;
}

static int shtcx_write_command(const struct device *dev, uint16_t cmd)
{
	uint8_t tx_buf[2];

	sys_put_be16(cmd, tx_buf);
	return i2c_write(shtcx_i2c_bus(dev), tx_buf, sizeof(tx_buf),
			 shtcx_i2c_address(dev));
}

static int shtcx_read_words(const struct device *dev, uint16_t cmd, uint16_t *data,
		     uint16_t num_words, uint16_t max_duration_us)
{
	const struct shtcx_config *cfg = dev->config;
	int status = 0;
	uint32_t raw_len = num_words * (SHTCX_WORD_LEN + SHTCX_CRC8_LEN);
	uint16_t temp16;
	uint8_t rx_buf[SHTCX_MAX_READ_LEN];
	int dst = 0;

	status = shtcx_write_command(dev, cmd);
	if (status != 0) {
		LOG_DBG("Failed to initiate read");
		return -EIO;
	}

	if (!cfg->clock_stretching) {
		k_sleep(K_USEC(max_duration_us));
	}

	status = i2c_read(shtcx_i2c_bus(dev), rx_buf, raw_len,
			  shtcx_i2c_address(dev));
	if (status != 0) {
		LOG_DBG("Failed to read data");
		return -EIO;
	}

	for (int i = 0; i < raw_len; i += (SHTCX_WORD_LEN + SHTCX_CRC8_LEN)) {
		temp16 = sys_get_be16(&rx_buf[i]);
		if (shtcx_compute_crc(temp16) != rx_buf[i+2]) {
			LOG_DBG("invalid received invalid crc");
			return -EIO;
		}

		data[dst++] = temp16;
	}

	return 0;
}

static int shtcx_sleep(const struct device *dev)
{
	if (shtcx_write_command(dev, SHTCX_CMD_SLEEP) < 0) {
		return -EIO;
	}

	return 0;
}

static int shtcx_wakeup(const struct device *dev)
{
	if (shtcx_write_command(dev, SHTCX_CMD_WAKEUP)) {
		return -EIO;
	}

	k_sleep(K_USEC(100));
	return 0;
}

static int shtcx_sample_fetch(const struct device *dev,
			       enum sensor_channel chan)
{
	struct shtcx_data *data = dev->data;
	const struct shtcx_config *cfg = dev->config;

	__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL);

	if (cfg->chip == SHTC3) {
		if (shtcx_wakeup(dev)) {
			return -EIO;
		}
	}

	if (shtcx_read_words(dev,
			     measure_cmd[cfg->measure_mode][cfg->clock_stretching],
			     (uint16_t *)&data->sample, 2,
			     measure_wait_us[cfg->chip][cfg->measure_mode]) < 0) {
		LOG_DBG("Failed read measurements!");
		return -EIO;
	}

	if (cfg->chip == SHTC3) {
		if (shtcx_sleep(dev)) {
			LOG_DBG("Failed to initiate sleep");
			return -EIO;
		}
	}

	return 0;
}

static int shtcx_channel_get(const struct device *dev,
			      enum sensor_channel chan,
			      struct sensor_value *val)
{
	const struct shtcx_data *data = dev->data;

	if (chan == SENSOR_CHAN_AMBIENT_TEMP) {
		shtcx_temperature_from_raw(data->sample.temp, val);
	} else if (chan == SENSOR_CHAN_HUMIDITY) {
		shtcx_humidity_from_raw(data->sample.humidity, val);
	} else {
		return -ENOTSUP;
	}

	return 0;
}

static const struct sensor_driver_api shtcx_driver_api = {
	.sample_fetch = shtcx_sample_fetch,
	.channel_get = shtcx_channel_get,
};

static int shtcx_init(const struct device *dev)
{
	const struct shtcx_config *cfg = dev->config;
	uint16_t product_id;

	if (device_is_ready(cfg->bus) ==  0) {
		LOG_DBG("i2c bus is not ready");
		return -ENODEV;
	}

	k_sleep(K_USEC(SHTCX_POWER_UP_TIME_US));
	if (cfg->chip == SHTC3) {
		if (shtcx_wakeup(dev)) {
			LOG_ERR("Wakeup failed");
			return -EIO;
		}
	}

	if (shtcx_write_command(dev, SHTCX_CMD_SOFT_RESET) < 0) {
		LOG_ERR("soft reset failed");
		return -EIO;
	}

	k_sleep(K_USEC(SHTCX_SOFT_RESET_TIME_US));
	if (shtcx_read_words(dev, SHTCX_CMD_READ_ID, &product_id, 1, 0) < 0) {
		LOG_ERR("Failed to read product id!");
		return -EIO;
	}

	if (cfg->chip == SHTC1) {
		if ((product_id & SHTC1_ID_MASK) != SHTC1_ID_VALUE) {
			LOG_ERR("Device is not a SHTC1");
			return -EINVAL;
		}
	}
	if (cfg->chip == SHTC3) {
		if ((product_id & SHTC3_ID_MASK) != SHTC3_ID_VALUE) {
			LOG_ERR("Device is not a SHTC3");
			return -EINVAL;
		}
		shtcx_sleep(dev);
	}

	LOG_DBG("Clock-stretching enabled: %d", cfg->clock_stretching);
	LOG_DBG("Measurement mode: %d", cfg->measure_mode);
	LOG_DBG("Init SHTCX");
	return 0;
}

#define SHTCX_CONFIG(inst)						       \
	{								       \
		.bus = DEVICE_DT_GET(DT_INST_BUS(inst)),		       \
		.base_address = DT_INST_REG_ADDR(inst),			       \
		.chip = DT_INST_ENUM_IDX(inst, chip),			       \
		.measure_mode = DT_INST_ENUM_IDX(inst, measure_mode),	       \
		.clock_stretching = DT_INST_PROP(inst, clock_stretching)       \
	}

#define SHTCX_DEFINE(inst)						\
	static struct shtcx_data shtcx_data_##inst;			\
	static struct shtcx_config shtcx_config_##inst =		\
		SHTCX_CONFIG(inst);					\
	DEVICE_DT_INST_DEFINE(inst,					\
			      shtcx_init,				\
			      NULL,					\
			      &shtcx_data_##inst,			\
			      &shtcx_config_##inst,			\
			      POST_KERNEL,				\
			      CONFIG_SENSOR_INIT_PRIORITY,		\
			      &shtcx_driver_api);

DT_INST_FOREACH_STATUS_OKAY(SHTCX_DEFINE)
