/*
 * Copyright (c) 2016 Intel Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @file Sample app to utilize APDS-9960 Sensor on Arduino 101 (ARC).
 *
 * The SparkFun RGB and Gesture Sensor was being used:
 *   https://www.sparkfun.com/products/12787
 *
 * This sample app is to read RGB value from the APDS-9960 sensor
 * and to display the color through the APA102C LED.
 *
 * For APA102C, on ARC side of Arduino 101:
 * 1. GPIO_SS_2 is on AD0 (for APA102C data)
 * 2. GPIO_SS_3 is on AD1 (for APA102C clock)
 *
 * The gpio_dw driver is being used for bit-banging to control
 * the APA102C LED..
 *
 * The APA102/C requires 5V data and clock signals, so logic
 * level shifter (preferred) or pull-up resistors are needed.
 * Make sure the pins are 5V tolerant if using pull-up
 * resistors.
 *
 * WARNING: the APA102C are very bright even at low settings.
 * Protect your eyes and do not look directly into those LEDs.
 */

#include <zephyr.h>

#if defined(CONFIG_STDOUT_CONSOLE)
#include <stdio.h>
#define PRINT           printf
#else
#include <misc/printk.h>
#define PRINT           printk
#endif

#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 {
	uint8_t		raw[8];
	struct {
		uint8_t		cdatal;
		uint8_t		cdatah;
		uint8_t		rdatal;
		uint8_t		rdatah;
		uint8_t		gdatal;
		uint8_t		gdatah;
		uint8_t		bdatal;
		uint8_t		bdatah;
	} ch;
};

void apa102c_rgb_send(struct device *gpio_dev, uint32_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, uint32_t rgb)
{
	apa102c_rgb_send(gpio_dev, APA102C_START_FRAME);
	apa102c_rgb_send(gpio_dev, rgb);
	apa102c_rgb_send(gpio_dev, APA102C_END_FRAME);
}

void apds9960_reg_write(struct device *i2c_dev,
			uint8_t reg_addr, uint8_t reg_val)
{
	struct i2c_msg msg;
	uint8_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) {
		PRINT("Cannot write APDS9960 reg 0x%X to 0x%X\n",
		      reg_addr, reg_val);

		while (ret) {
			/* spin if error */
		}
	}
}

void apds9960_reg_read(struct device *i2c_dev, uint8_t reg_addr,
		       uint8_t *data, uint8_t data_len)
{
	struct i2c_msg msgs[2];
	uint8_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) {
		PRINT("Cannot read from APDS9960 reg 0x%X\n", reg_addr);

		while (ret) {
			/* spin if error */
		}
	}
}

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)
{
	uint8_t status;

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

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

		sys_thread_busy_wait(5 * USEC_PER_MSEC);
	}
}

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) {
		PRINT("Cannot find %s!\n", GPIO_DRV_NAME);

		while (!gpio_dev) {
			/* spin if error */
		};
	}

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

		while (!i2c_dev) {
			/* spin if error */
		};
	}

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

	ret = gpio_pin_configure(gpio_dev, GPIO_CLK_PIN, (GPIO_DIR_OUT));
	if (ret) {
		PRINT("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, (uint8_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);
			PRINT("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);
			PRINT("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);
		}
	}
}
