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

#include <zephyr.h>
#include <stdio.h>
#include <device.h>
#include <gpio.h>
#include <i2c.h>
#include <sys_clock.h>
#include <misc/util.h>

#define SLEEP_MSEC	200

#define GPIO_DATA_PIN	2
#define GPIO_CLK_PIN	3
#define GPIO_NAME	"GPIO_SS_"

#define GPIO_DRV_NAME	"GPIO_0"

#define APA102C_START_FRAME	0x00000000
#define APA102C_END_FRAME	0xFFFFFFFF
#define APA102C_BRIGHTNESS	0xE2000000
#define APA102C_BRIGHTNESS_MASK	0xFF000000

#define I2C_DRV_NAME		"I2C_0"
#define APDS9960_ADDR		0x39

union rgbc_t {
	u8_t		raw[8];
	struct {
		u8_t		cdatal;
		u8_t		cdatah;
		u8_t		rdatal;
		u8_t		rdatah;
		u8_t		gdatal;
		u8_t		gdatah;
		u8_t		bdatal;
		u8_t		bdatah;
	} ch;
};

void apa102c_rgb_send(struct device *gpio_dev, u32_t rgb)
{
	int i;

	for (i = 0; i < 32; i++) {
		/* MSB goes in first */
		gpio_pin_write(gpio_dev, GPIO_DATA_PIN, !!(rgb & 0x80000000));

		/* Latch data into LED */
		gpio_pin_write(gpio_dev, GPIO_CLK_PIN, 1);
		gpio_pin_write(gpio_dev, GPIO_CLK_PIN, 0);

		rgb <<= 1;
	}
}

void apa102c_led_program(struct device *gpio_dev, u32_t rgb)
{
	apa102c_rgb_send(gpio_dev, APA102C_START_FRAME);
	apa102c_rgb_send(gpio_dev, rgb);
	apa102c_rgb_send(gpio_dev, APA102C_END_FRAME);
}

int apds9960_reg_write(struct device *i2c_dev,
			u8_t reg_addr, u8_t reg_val)
{
	struct i2c_msg msg;
	u8_t data[2];
	int ret;

	msg.buf = data;
	msg.flags = I2C_MSG_WRITE | I2C_MSG_STOP;

	/* Enable Power (PON) so we can configure the sensor */
	data[0] = reg_addr;
	data[1] = reg_val;
	msg.len = 2;

	ret = i2c_transfer(i2c_dev, &msg, 1, APDS9960_ADDR);
	if (ret) {
		printf("Cannot write APDS9960 reg 0x%X to 0x%X\n",
		      reg_addr, reg_val);
	}

	return ret;
}

int apds9960_reg_read(struct device *i2c_dev, u8_t reg_addr,
		       u8_t *data, u8_t data_len)
{
	struct i2c_msg msgs[2];
	u8_t reg_data;
	int ret;

	/* Access RGBC data register */
	reg_data = reg_addr;
	msgs[0].buf = &reg_data;
	msgs[0].len = 1;
	msgs[0].flags = I2C_MSG_WRITE;

	/* Read 8 bytes of RGBC values */
	msgs[1].buf = data;
	msgs[1].len = data_len;
	msgs[1].flags = I2C_MSG_READ | I2C_MSG_RESTART | I2C_MSG_STOP;

	ret = i2c_transfer(i2c_dev, msgs, 2, APDS9960_ADDR);
	if (ret) {
		printf("Cannot read from APDS9960 reg 0x%X\n", reg_addr);
	}

	return ret;
}

void apds9960_setup(struct device *i2c_dev, int gain)
{
	/* Enable Power (PON) so we can configure the sensor */
	apds9960_reg_write(i2c_dev, 0x80, 0x01);

	/* Max out the ADC values.
	 * So every ADC cycle is 200ms, and max
	 * ADC value is 65535.
	 */
	apds9960_reg_write(i2c_dev, 0x81, 0xB6);

	/* ALS LEDs Gain */
	apds9960_reg_write(i2c_dev, 0x8F, (gain & 0x03));

	/* Enable Power (PON) and ALS*/
	apds9960_reg_write(i2c_dev, 0x80, 0x03);
}

void apds9960_als_valid_wait(struct device *i2c_dev)
{
	u8_t status;

	while (1) {
		apds9960_reg_read(i2c_dev, 0x93, &status, 1);

		if (status & BIT(0)) {
			break;
		}

		k_sleep(5);
	}
}

void main(void)
{
	struct device *gpio_dev, *i2c_dev;
	int ret;
	union rgbc_t rgbc;
	int led_rgb;
	int als_gain = 0;

	gpio_dev = device_get_binding(GPIO_DRV_NAME);
	if (!gpio_dev) {
		printf("Cannot find %s!\n", GPIO_DRV_NAME);
		return;
	}

	i2c_dev = device_get_binding(I2C_DRV_NAME);
	if (!i2c_dev) {
		printf("Cannot find %s!\n", I2C_DRV_NAME);
		return;
	}

	/*
	 * Setup GPIO outputs
	 */
	ret = gpio_pin_configure(gpio_dev, GPIO_DATA_PIN, (GPIO_DIR_OUT));
	if (ret) {
		printf("Error configuring " GPIO_NAME "%d!\n", GPIO_DATA_PIN);
	}

	ret = gpio_pin_configure(gpio_dev, GPIO_CLK_PIN, (GPIO_DIR_OUT));
	if (ret) {
		printf("Error configuring " GPIO_NAME "%d!\n", GPIO_CLK_PIN);
	}

	/*
	 * Initialize the APDS9960 sensor with 1x ALS gain
	 */
	apds9960_setup(i2c_dev, als_gain);

	while (1) {
		apds9960_als_valid_wait(i2c_dev);

		apds9960_reg_read(i2c_dev, 0x94, (u8_t *)&rgbc, 8);

		/* Change the gain if it is too bright or too dark.
		 * Note there is no logic to prevent it from
		 * bouncing between two gain settings.
		 */
		if ((rgbc.ch.cdatah < 0x10) && (als_gain != 3)) {
			/* More gain if too dark */
			als_gain++;
			if (als_gain > 3) {
				als_gain = 3;
			}

			apds9960_setup(i2c_dev, als_gain);
			printf("GAIN ==> %d\n", als_gain);
		} else if ((rgbc.ch.cdatah > 0xEF) && (als_gain != 0)) {
			/* Less gain if too bright */
			als_gain--;
			if (als_gain < 0) {
				als_gain = 0;
			}

			apds9960_setup(i2c_dev, als_gain);
			printf("GAIN ==> %d\n", als_gain);
		} else {
			/* Only program the LED when gain settles.
			 * Or else the LED would suddenly go all
			 * bright or dark before settling to
			 * the final value.
			 */
			led_rgb = (rgbc.ch.bdatah << 16)
				  + (rgbc.ch.gdatah << 8)
				  + (rgbc.ch.rdatah)
				  + APA102C_BRIGHTNESS;

			apa102c_led_program(gpio_dev, led_rgb);
		}
	}
}
