/*
 * Copyright (c) 2022, Michal Morsisko
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT rohm_bh1750

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

LOG_MODULE_REGISTER(BH1750, CONFIG_SENSOR_LOG_LEVEL);

#define BH1750_CONTINUOUS_HIGH_RES_MODE                 0x10
#define BH1750_CONTINUOUS_HIGH_RES_MODE_2               0x11
#define BH1750_CONTINUOUS_LOW_RES_MODE                  0x13
#define BH1750_ONE_TIME_HIGH_RES_MODE                   0x20
#define BH1750_ONE_TIME_HIGH_RES_MODE_2                 0x21
#define BH1750_ONE_TIME_LOW_RES_MODE                    0x23
#define BH1750_MTREG_HIGH_BYTE                          0x40
#define BH1750_MTREG_LOW_BYTE                           0x60
#define BH1750_MTREG_HIGH_BYTE_MASK                     0xE0
#define BH1750_MTREG_LOW_BYTE_MASK                      0x1F

#define BH1750_DEFAULT_MTREG                            69U
#define BH1750_LOW_RES_MODE_MAX_WAIT                    24U
#define BH1750_HIGH_RES_MODE_MAX_WAIT                   180U
#define BH1750_LOW_RES_MODE_TYPICAL_WAIT                16U
#define BH1750_HIGH_RES_MODE_TYPICAL_WAIT               120U

#define BH1750_LOW_RES_DTS_ENUM                         0U
#define BH1750_HIGH_RES_DTS_ENUM                        1U
#define BH1750_HIGH_RES_2_DTS_ENUM                      2U

struct bh1750_dev_config {
	struct i2c_dt_spec bus;
	uint8_t resolution;
	uint8_t mtreg;
};

struct bh1750_data {
	uint16_t sample;
};

static int bh1750_opcode_read(const struct device *dev, uint8_t opcode,
			      uint16_t *val)
{
	const struct bh1750_dev_config *cfg = dev->config;
	int rc;

	rc = i2c_burst_read_dt(&cfg->bus, opcode, (uint8_t *)val, 2);
	if (rc < 0) {
		return rc;
	}

	*val = sys_be16_to_cpu(*val);
	return 0;
}

static int bh1750_opcode_write(const struct device *dev, uint8_t opcode)
{
	const struct bh1750_dev_config *cfg = dev->config;

	return i2c_write_dt(&cfg->bus, &opcode, 1);
}

static int bh1750_mtreg_write(const struct device *dev, uint8_t mtreg)
{
	int rc;
	uint8_t high_byte = mtreg & BH1750_MTREG_HIGH_BYTE_MASK;
	uint8_t low_byte = mtreg & BH1750_MTREG_LOW_BYTE_MASK;

	rc = bh1750_opcode_write(dev, BH1750_MTREG_HIGH_BYTE | (high_byte >> 5));
	if (rc < 0) {
		LOG_ERR("%s, Failed to write high byte of mtreg!",
			dev->name);
		return rc;
	}

	rc = bh1750_opcode_write(dev, BH1750_MTREG_LOW_BYTE | low_byte);
	if (rc < 0) {
		LOG_ERR("%s, Failed to write low byte of mtreg!",
			dev->name);
		return rc;
	}

	return 0;
}

static uint8_t bh1750_get_mode_from_dts_device(const struct device *dev)
{
	const struct bh1750_dev_config *cfg = dev->config;

	if (cfg->resolution == BH1750_HIGH_RES_2_DTS_ENUM) {
		return BH1750_ONE_TIME_HIGH_RES_MODE_2;
	} else if (cfg->resolution == BH1750_HIGH_RES_DTS_ENUM) {
		return BH1750_ONE_TIME_HIGH_RES_MODE;
	} else {
		return BH1750_ONE_TIME_LOW_RES_MODE;
	}
}

static int bh1750_get_wait_time_from_dts_device(const struct device *dev)
{
	const struct bh1750_dev_config *cfg = dev->config;

	if (cfg->resolution == BH1750_HIGH_RES_2_DTS_ENUM) {
		return BH1750_HIGH_RES_MODE_MAX_WAIT;
	} else if (cfg->resolution == BH1750_HIGH_RES_DTS_ENUM) {
		return BH1750_HIGH_RES_MODE_MAX_WAIT;
	} else {
		return BH1750_LOW_RES_MODE_MAX_WAIT;
	}
}

static int bh1750_sample_fetch(const struct device *dev,
			       enum sensor_channel chan)
{
	const struct bh1750_dev_config *cfg = dev->config;
	struct bh1750_data *drv_data = dev->data;
	const int max_wait = bh1750_get_wait_time_from_dts_device(dev);
	const uint8_t mode = bh1750_get_mode_from_dts_device(dev);
	int rc;
	int wait_time;

	if (chan != SENSOR_CHAN_ALL &&
	    chan != SENSOR_CHAN_LIGHT) {
		return -ENOTSUP;
	}

	/* Start the measurement */
	rc = bh1750_opcode_write(dev, mode);
	if (rc < 0) {
		LOG_ERR("%s, Failed to start measurement!",
			dev->name);
		return rc;
	}

	/* Calculate measurement time */
	wait_time = (max_wait * (cfg->mtreg * 10000 / BH1750_DEFAULT_MTREG)) / 10000;

	/* Wait for the measurement to be stored in the sensor memory */
	k_msleep(wait_time);

	/* Fetch result */
	rc = bh1750_opcode_read(dev, mode, &drv_data->sample);
	if (rc < 0) {
		LOG_ERR("%s: Failed to read measurement result!",
			dev->name);
		return rc;
	}

	return 0;
}

static int bh1750_channel_get(const struct device *dev,
			      enum sensor_channel chan,
			      struct sensor_value *val)
{
	const struct bh1750_dev_config *cfg = dev->config;
	struct bh1750_data *drv_data = dev->data;
	uint32_t tmp;

	if (chan != SENSOR_CHAN_ALL &&
	    chan != SENSOR_CHAN_LIGHT) {
		return -ENOTSUP;
	}

	/* See datasheet (Technical note 11046EDT01), page 11
	 * https://www.mouser.com/datasheet/2/348/Rohm_11162017_ROHMS34826-1-1279292.pdf
	 * for more information how to convert raw sample to lx
	 */
	tmp = (drv_data->sample * 1000 / 12) * (BH1750_DEFAULT_MTREG * 100 / cfg->mtreg);

	if (cfg->resolution == BH1750_HIGH_RES_2_DTS_ENUM) {
		tmp /= 2;
	}

	val->val1 = tmp / 10000;
	val->val2 = (tmp % 10000) * 100;

	return 0;
}

static const struct sensor_driver_api bh1750_driver_api = {
	.sample_fetch = bh1750_sample_fetch,
	.channel_get = bh1750_channel_get
};

static int bh1750_init(const struct device *dev)
{
	const struct bh1750_dev_config *cfg = dev->config;

	if (!device_is_ready(cfg->bus.bus)) {
		LOG_ERR("I2C dev %s not ready", cfg->bus.bus->name);
		return -ENODEV;
	}

	if (cfg->mtreg != BH1750_DEFAULT_MTREG) {
		bh1750_mtreg_write(dev, cfg->mtreg);
	}

	return 0;
}

#define DEFINE_BH1750(_num)							       \
	static struct bh1750_data bh1750_data_##_num;				       \
	static const struct bh1750_dev_config bh1750_config_##_num = {		       \
		.bus = I2C_DT_SPEC_INST_GET(_num),				       \
		.mtreg = DT_INST_PROP(_num, mtreg),				       \
		.resolution = DT_INST_PROP(_num, resolution)			       \
	};									       \
	SENSOR_DEVICE_DT_INST_DEFINE(_num, bh1750_init, NULL,				       \
			      &bh1750_data_##_num, &bh1750_config_##_num, POST_KERNEL, \
			      CONFIG_SENSOR_INIT_PRIORITY, &bh1750_driver_api);

DT_INST_FOREACH_STATUS_OKAY(DEFINE_BH1750)
