/*
 * Copyright (c) 2019 Thomas Schmid <tom@lfence.de>
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <init.h>
#include <kernel.h>
#include <sys/byteorder.h>
#include <drivers/sensor.h>
#include <sys/__assert.h>

#include "ms5607.h"

#define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(ms5607);

static void ms5607_compensate(struct ms5607_data *data,
			      const s32_t adc_temperature,
			      const s32_t adc_pressure)
{
	s64_t dT;
	s64_t OFF;
	s64_t SENS;
	s64_t temp_sq;
	s64_t Ti;
	s64_t OFFi;
	s64_t SENSi;

	/* first order compensation as per datasheet
	 * (https://www.te.com/usa-en/product-CAT-BLPS0035.html) section
	 * PRESSURE AND TEMPERATURE CALCULATION
	 */

	dT = adc_temperature - ((u32_t)(data->t_ref) << 8);
	data->temperature = 2000 + (dT * data->tempsens) / (1ll << 23);
	OFF = ((s64_t)(data->off_t1) << 17) + (dT * data->tco) / (1ll << 6);
	SENS = ((s64_t)(data->sens_t1) << 16) + (dT * data->tcs) / (1ll << 7);

	/* Second order compensation as per datasheet
	 * (https://www.te.com/usa-en/product-CAT-BLPS0035.html) section
	 * SECOND ORDER TEMPERATURE COMPENSATION
	 */

	temp_sq = (data->temperature - 2000) * (data->temperature - 2000);
	if (data->temperature < 2000) {
		Ti = (dT * dT) / (1ll << 31);
		OFFi = (61ll * temp_sq) / (1ll << 4);
		SENSi = 2ll * temp_sq;
		if (data->temperature < -1500) {
			temp_sq = (data->temperature + 1500) *
				  (data->temperature + 1500);
			OFFi += 15ll * temp_sq;
			SENSi += 8ll * temp_sq;
		}
	} else {
		SENSi = 0;
		OFFi = 0;
		Ti = 0;
	}

	OFF -= OFFi;
	SENS -= SENSi;

	data->temperature -= Ti;
	data->pressure = (SENS * (s64_t)adc_pressure / (1ll << 21) - OFF) /
			 (1ll << 15);
}

static int ms5607_read_prom(const struct ms5607_data *data, u8_t cmd,
			    u16_t *val)
{
	int err;

	err = data->tf->read_prom(data, cmd, val);
	if (err < 0) {
		LOG_ERR("Error reading prom");
		return err;
	}

	return 0;
}

static int ms5607_get_measurement(const struct ms5607_data *data,
				  u32_t *val,
				  u8_t cmd,
				  u8_t delay)
{
	int err;

	*val = 0U;

	err = data->tf->start_conversion(data, cmd);
	if (err < 0) {
		return err;
	}

	k_sleep(delay);

	err = data->tf->read_adc(data, val);
	if (err < 0) {
		return err;
	}

	return 0;
}

static int ms5607_sample_fetch(struct device *dev, enum sensor_channel channel)
{
	struct ms5607_data *data = dev->driver_data;
	int err;
	u32_t adc_pressure, adc_temperature;

	__ASSERT_NO_MSG(channel == SENSOR_CHAN_ALL);

	err = ms5607_get_measurement(data,
				     &adc_pressure,
				     data->pressure_conv_cmd,
				     data->pressure_conv_delay);
	if (err < 0) {
		return err;
	}

	err = ms5607_get_measurement(data,
				     &adc_temperature,
				     data->temperature_conv_cmd,
				     data->temperature_conv_delay);
	if (err < 0) {
		return err;
	}

	ms5607_compensate(data, adc_temperature, adc_pressure);
	return 0;
}

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

	switch (chan) {
	case SENSOR_CHAN_AMBIENT_TEMP:
		val->val1 = data->temperature / 100;
		val->val2 = data->temperature % 100 * 10000;
		break;
	case SENSOR_CHAN_PRESS:
		val->val1 = data->pressure / 100;
		val->val2 = data->pressure % 100 * 10000;
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static int ms5607_attr_set(struct device *dev, enum sensor_channel chan,
			   enum sensor_attribute attr,
			   const struct sensor_value *val)
{
	struct ms5607_data *data = dev->driver_data;
	u8_t p_conv_cmd, t_conv_cmd, conv_delay;

	if (attr != SENSOR_ATTR_OVERSAMPLING) {
		return -ENOTSUP;
	}

	switch (val->val1) {
	case 4096:
		p_conv_cmd = MS5607_CMD_CONV_P_4096;
		t_conv_cmd = MS5607_CMD_CONV_T_4096;
		conv_delay = 9U;
		break;
	case 2048:
		p_conv_cmd = MS5607_CMD_CONV_P_2048;
		t_conv_cmd = MS5607_CMD_CONV_T_2048;
		conv_delay = 5U;
		break;
	case 1024:
		p_conv_cmd = MS5607_CMD_CONV_P_1024;
		t_conv_cmd = MS5607_CMD_CONV_T_1024;
		conv_delay = 3U;
		break;
	case 512:
		p_conv_cmd = MS5607_CMD_CONV_P_512;
		t_conv_cmd = MS5607_CMD_CONV_T_512;
		conv_delay = 2U;
		break;
	case 256:
		p_conv_cmd = MS5607_CMD_CONV_P_256;
		t_conv_cmd = MS5607_CMD_CONV_T_256;
		conv_delay = 1U;
		break;
	default:
		LOG_ERR("invalid oversampling rate %d", val->val1);
		return -EINVAL;
	}

	switch (chan) {
	case SENSOR_CHAN_ALL:
		data->pressure_conv_cmd = p_conv_cmd;
		data->temperature_conv_cmd = t_conv_cmd;
		data->temperature_conv_delay = conv_delay;
		data->pressure_conv_delay = conv_delay;
		break;
	case SENSOR_CHAN_PRESS:
		data->pressure_conv_cmd = p_conv_cmd;
		data->pressure_conv_delay = conv_delay;
		break;
	case SENSOR_CHAN_AMBIENT_TEMP:
		data->temperature_conv_cmd = t_conv_cmd;
		data->temperature_conv_delay = conv_delay;
		break;
	default:
		return -ENOTSUP;
	}

	return 0;
}

static const struct ms5607_config ms5607_config = {
	.ms5607_device_name = DT_INST_0_MEAS_MS5607_BUS_NAME,
};

static int ms5607_init(struct device *dev)
{
	const struct ms5607_config *const config = dev->config->config_info;
	struct ms5607_data *data = dev->driver_data;
	struct sensor_value val;
	int err;

	data->ms5607_device = device_get_binding(config->ms5607_device_name);
	if (!data->ms5607_device) {
		LOG_ERR("master not found: %s", config->ms5607_device_name);
		return -EINVAL;
	}

#ifdef DT_MEAS_MS5607_BUS_SPI
	ms5607_spi_init(dev);
#else
	BUILD_ASSERT_MSG(1, "I2c interface not implemented yet");
#endif

	data->pressure = 0;
	data->temperature = 0;


	val.val1 = MS5607_PRES_OVER_DEFAULT;
	err = ms5607_attr_set(dev, SENSOR_CHAN_PRESS, SENSOR_ATTR_OVERSAMPLING,
			      &val);
	if (err < 0) {
		return err;
	}

	val.val1 = MS5607_TEMP_OVER_DEFAULT;
	err = ms5607_attr_set(dev, SENSOR_CHAN_AMBIENT_TEMP,
			      SENSOR_ATTR_OVERSAMPLING, &val);
	if (err < 0) {
		return err;
	}

	err = data->tf->reset(data);
	if (err < 0) {
		return err;
	}

	k_sleep(K_MSEC(2));

	err = ms5607_read_prom(data, MS5607_CMD_CONV_READ_OFF_T1,
			       &data->off_t1);
	if (err < 0) {
		return err;
	}

	LOG_DBG("OFF_T1: %d", data->off_t1);

	err = ms5607_read_prom(data, MS5607_CMD_CONV_READ_SENSE_T1,
			       &data->sens_t1);
	if (err < 0) {
		return err;
	}

	LOG_DBG("SENSE_T1: %d", data->sens_t1);

	err = ms5607_read_prom(data, MS5607_CMD_CONV_READ_T_REF, &data->t_ref);
	if (err < 0) {
		return err;
	}

	LOG_DBG("T_REF: %d", data->t_ref);

	err = ms5607_read_prom(data, MS5607_CMD_CONV_READ_TCO, &data->tco);
	if (err < 0) {
		return err;
	}

	LOG_DBG("TCO: %d", data->tco);

	err = ms5607_read_prom(data, MS5607_CMD_CONV_READ_TCS, &data->tcs);
	if (err < 0) {
		return err;
	}

	LOG_DBG("TCS: %d", data->tcs);

	err = ms5607_read_prom(data, MS5607_CMD_CONV_READ_TEMPSENS,
			       &data->tempsens);
	if (err < 0) {
		return err;
	}

	LOG_DBG("TEMPSENS: %d", data->tempsens);

	return 0;
}

static const struct sensor_driver_api ms5607_api_funcs = {
	.attr_set = ms5607_attr_set,
	.sample_fetch = ms5607_sample_fetch,
	.channel_get = ms5607_channel_get,
};

static struct ms5607_data ms5607_data;

DEVICE_AND_API_INIT(ms5607,
		    DT_INST_0_MEAS_MS5607_LABEL,
		    ms5607_init,
		    &ms5607_data,
		    &ms5607_config,
		    POST_KERNEL,
		    CONFIG_SENSOR_INIT_PRIORITY,
		    &ms5607_api_funcs);
