/*
 * Copyright (c) 2021 Leonard Pollak
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT ti_ina219

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

#include "ina219.h"

LOG_MODULE_REGISTER(INA219, CONFIG_SENSOR_LOG_LEVEL);

static int ina219_reg_read(const struct device *dev,
		uint8_t reg_addr,
		uint16_t *reg_data)
{
	const struct ina219_config *cfg = dev->config;
	uint8_t rx_buf[2];
	int rc;

	rc = i2c_write_read_dt(&cfg->bus,
			&reg_addr, sizeof(reg_addr),
			rx_buf, sizeof(rx_buf));

	*reg_data = sys_get_be16(rx_buf);

	return rc;
}

static int ina219_reg_write(const struct device *dev,
		uint8_t addr,
		uint16_t reg_data)
{
	const struct ina219_config *cfg = dev->config;
	uint8_t tx_buf[3];

	tx_buf[0] = addr;
	sys_put_be16(reg_data, &tx_buf[1]);

	return i2c_write_dt(&cfg->bus, tx_buf, sizeof(tx_buf));
}

static int ina219_reg_field_update(const struct device *dev,
		uint8_t addr,
		uint16_t mask,
		uint16_t field)
{
	uint16_t reg_data;
	int rc;

	rc = ina219_reg_read(dev, addr, &reg_data);
	if (rc) {
		return rc;
	}

	reg_data = (reg_data & ~mask) | field;

	return ina219_reg_write(dev, addr, reg_data);
}

static int ina219_set_msr_delay(const struct device *dev)
{
	const struct ina219_config *cfg = dev->config;
	struct ina219_data *data = dev->data;

	data->msr_delay = ina219_conv_delay(cfg->badc) +
		ina219_conv_delay(cfg->sadc);
	return 0;
}

static int ina219_set_config(const struct device *dev)
{
	const struct ina219_config *cfg = dev->config;
	uint16_t reg_data;

	reg_data = (cfg->brng & INA219_BRNG_MASK) << INA219_BRNG_SHIFT |
		(cfg->pg & INA219_PG_MASK) << INA219_PG_SHIFT |
		(cfg->badc & INA219_ADC_MASK) << INA219_BADC_SHIFT |
		(cfg->sadc & INA219_ADC_MASK) << INA219_SADC_SHIFT |
		(cfg->mode & INA219_MODE_NORMAL);

	return ina219_reg_write(dev, INA219_REG_CONF, reg_data);
}

static int ina219_set_calib(const struct device *dev)
{
	const struct ina219_config *cfg = dev->config;
	uint16_t cal;

	cal = INA219_SCALING_FACTOR / ((cfg->r_shunt) * (cfg->current_lsb));

	return ina219_reg_write(dev, INA219_REG_CALIB, cal);
}

static int ina219_sample_fetch(const struct device *dev,
			       enum sensor_channel chan)
{
	struct ina219_data *data = dev->data;
	uint16_t status;
	uint16_t tmp;
	int rc;

	if (chan != SENSOR_CHAN_ALL &&
		chan != SENSOR_CHAN_VOLTAGE &&
		chan != SENSOR_CHAN_POWER &&
		chan != SENSOR_CHAN_CURRENT) {
		return -ENOTSUP;
	}

	/* Trigger measurement and wait for completion */
	rc = ina219_reg_field_update(dev,
				    INA219_REG_CONF,
				    INA219_MODE_MASK,
				    INA219_MODE_NORMAL);
	if (rc) {
		LOG_ERR("Failed to start measurement.");
		return rc;
	}

	k_sleep(K_USEC(data->msr_delay));

	rc = ina219_reg_read(dev, INA219_REG_V_BUS, &status);
	if (rc) {
		LOG_ERR("Failed to read device status.");
		return rc;
	}

	while (!(INA219_CNVR_RDY(status))) {
		rc = ina219_reg_read(dev, INA219_REG_V_BUS, &status);
		if (rc) {
			LOG_ERR("Failed to read device status.");
			return rc;
		}
		k_sleep(K_USEC(INA219_WAIT_MSR_RETRY));
	}

	/* Check for overflow */
	if (INA219_OVF_STATUS(status)) {
		LOG_WRN("Power and/or Current calculations are out of range.");
	}

	if (chan == SENSOR_CHAN_ALL ||
		chan == SENSOR_CHAN_VOLTAGE) {

		rc = ina219_reg_read(dev, INA219_REG_V_BUS, &tmp);
		if (rc) {
			LOG_ERR("Error reading bus voltage.");
			return rc;
		}
		data->v_bus = INA219_VBUS_GET(tmp);
	}

	if (chan == SENSOR_CHAN_ALL ||
		chan == SENSOR_CHAN_POWER)	{

		rc = ina219_reg_read(dev, INA219_REG_POWER, &tmp);
		if (rc) {
			LOG_ERR("Error reading power register.");
			return rc;
		}
		data->power = tmp;
	}

	if (chan == SENSOR_CHAN_ALL ||
		chan == SENSOR_CHAN_CURRENT) {

		rc = ina219_reg_read(dev, INA219_REG_CURRENT, &tmp);
		if (rc) {
			LOG_ERR("Error reading current register.");
			return rc;
		}
		data->current = tmp;
	}

	return rc;
}

static int ina219_channel_get(const struct device *dev,
			      enum sensor_channel chan,
			      struct sensor_value *val)
{
	const struct ina219_config *cfg = dev->config;
	struct ina219_data *data = dev->data;
	double tmp;
	int8_t sign = 1;

	switch (chan) {
	case SENSOR_CHAN_VOLTAGE:
		tmp = data->v_bus * INA219_V_BUS_MUL;
		sensor_value_from_double(val, tmp);
		break;
	case SENSOR_CHAN_POWER:
		tmp = data->power * cfg->current_lsb * INA219_POWER_MUL * INA219_SI_MUL;
		sensor_value_from_double(val, tmp);
		break;
	case SENSOR_CHAN_CURRENT:
		if (INA219_SIGN_BIT(data->current)) {
			data->current = ~data->current + 1;
			sign = -1;
		}
		tmp = sign * data->current * cfg->current_lsb * INA219_SI_MUL;
		sensor_value_from_double(val, tmp);
		break;
	default:
		LOG_DBG("Channel not supported by device!");
		return -ENOTSUP;
	}

	return 0;
}

#ifdef CONFIG_PM_DEVICE
static int ina219_pm_ctrl(const struct device *dev, enum pm_device_action action)
{
	switch (action) {
	case PM_DEVICE_ACTION_RESUME:
		return ina219_init(dev);
	case PM_DEVICE_ACTION_SUSPEND:
		reg_val = INA219_MODE_SLEEP;
		break;
	case PM_DEVICE_ACTION_TURN_OFF:
		reg_val = INA219_MODE_OFF;
		break;
	default:
		return -ENOTSUP;
	}

	return ina219_reg_field_update(dev,
				INA219_REG_CONF,
				INA219_MODE_MASK,
				reg_val);
}
#endif /* CONFIG_PM_DEVICE */

static int ina219_init(const struct device *dev)
{
	const struct ina219_config *cfg = dev->config;
	int rc;

	if (!device_is_ready(cfg->bus.bus)) {
		LOG_ERR("Device not ready.");
		return -ENODEV;
	}

	rc = ina219_reg_write(dev, INA219_REG_CONF, INA219_RST);
	if (rc) {
		LOG_ERR("Could not reset device.");
		return rc;
	}

	rc = ina219_set_config(dev);
	if (rc) {
		LOG_ERR("Could not set configuration data.");
		return rc;
	}

	rc = ina219_set_calib(dev);
	if (rc) {
		LOG_DBG("Could not set calibration data.");
		return rc;
	}

	/* Set measurement delay */
	rc = ina219_set_msr_delay(dev);
	if (rc) {
		LOG_ERR("Could not get measurement delay.");
		return rc;
	}

	k_sleep(K_USEC(INA219_WAIT_STARTUP));

	return 0;
}

static const struct sensor_driver_api ina219_api = {
	.sample_fetch = ina219_sample_fetch,
	.channel_get = ina219_channel_get,
};


#define INA219_INIT(n)						\
	static struct ina219_data ina219_data_##n;		\
								\
	static const struct ina219_config ina219_config_##n = {	\
		.bus = I2C_DT_SPEC_INST_GET(n),			\
		.current_lsb = DT_INST_PROP(n, lsb_microamp),	\
		.r_shunt = DT_INST_PROP(n, shunt_milliohm),	\
		.brng = DT_INST_PROP(n, brng),			\
		.pg = DT_INST_PROP(n, pg),			\
		.badc = DT_INST_PROP(n, badc),			\
		.sadc = DT_INST_PROP(n, sadc),			\
		.mode = INA219_MODE_NORMAL			\
	};							\
								\
	DEVICE_DT_INST_DEFINE(n,				\
			      ina219_init,			\
			      ina219_pm_ctrl,\
			      &ina219_data_##n,			\
			      &ina219_config_##n,		\
			      POST_KERNEL,			\
			      CONFIG_SENSOR_INIT_PRIORITY,	\
			      &ina219_api);

DT_INST_FOREACH_STATUS_OKAY(INA219_INIT)
