/*
 * Copyright (c) 2016, Intel Corporation
 * All rights reserved.
 *
 */

#include "qm_ss_i2c.h"
#include "qm_ss_interrupt.h"
#include "qm_interrupt.h"
#include "qm_interrupt_router.h"
#include "qm_mailbox.h"
#include "qm_ss_isr.h"
#include "qm_isr.h"
#include "ss_clk.h"
#include "clk.h"
#include "get_ticks.h"
#include "qm_mailbox.h"
#include "ss_init.h"
#include "qm_isr.h"

#include "power_states.h"
#include "ss_power_states.h"
#include "qm_sensor_regs.h"
#include "soc_watch.h"
#include "qm_common.h"

/*
 * Disable Sensor printf output.
 * UART for printf is shared between x86 processor and sensor subsystem. To
 * avoid conflicts, initialisation of UART by sensor subsystem is disabled in
 * the Makefile and printf and puts calls are disabled hereafter.
 */
#define DISABLE_SENSOR_PRINTF 0
#if (DISABLE_SENSOR_PRINTF && QM_SENSOR)
#undef QM_PUTS
#undef QM_PRINTF
#define QM_PUTS(...)
#define QM_PRINTF(...)
#endif

#define WRITE_WAIT_TIME_US (50000)

#define SHT21_ADDR (0x40)
#define eTempHoldCmd (0xE3)
#define eRHumidityHoldCmd (0xE5)
#define eTempNoHoldCmd (0xF3)
#define eRHumidityNoHoldCmd (0xF5)


#define CM3592_I2C_ADDRESS 0x10
#define CM3592_CONGFIG_REG 0x00
#define CM3592_UV_REG      0x06
#define CM3592_UVB_REG     0x07
#define CM3592_IR_REG      0x0B
#define CM3592_ALS_REG     0x09


#define useUV (1)
//#define useI2C0 (1)


#if (QM_SENSOR)
#define QM_MBOX_PRINTF(...)
#else
#define QM_MBOX_PRINTF(...) printf(__VA_ARGS__)
#endif

qm_mbox_msg_t tx_data;
qm_mbox_msg_t rx_data;
qm_mbox_config_t mbox_rx_config;
qm_mbox_ch_t SSmbox_tx_channel= QM_MBOX_CH_0;
qm_mbox_ch_t SSmbox_rx_channel = QM_MBOX_CH_1;
volatile bool iSUpdate_Data;
static uint8_t test_counter;
//== i2c Read/Write Register functions ////////
int i2c_read_register(uint16_t addr, uint8_t reg, uint8_t *const data,
			     uint32_t len)
{
	int rc;
	qm_ss_i2c_status_t status;
#if (useI2C0)
	rc = qm_ss_i2c_master_write(QM_SS_I2C_0, addr, &reg, sizeof(reg), false,
				 &status);
#else
	rc = qm_ss_i2c_master_write(QM_SS_I2C_1, addr, &reg, sizeof(reg), false,
					 &status);
#endif

	if (rc != 0)
		return rc;
#if (useI2C0)
	rc = qm_ss_i2c_master_read(QM_SS_I2C_0, addr, data, len, true, &status);
#else
	rc = qm_ss_i2c_master_read(QM_SS_I2C_1, addr, data, len, true, &status);
#endif
	if (rc != 0){
		QM_PUTS("\t[Sensor] read_register2 Error!!!");
		return rc;
	}
	return 0;
}

int i2c_write_register(uint16_t addr, uint8_t reg, uint8_t data)
{
	int rc;
	qm_ss_i2c_status_t status;
#if (useI2C0)
	rc = qm_ss_i2c_master_write(QM_SS_I2C_0, addr, &reg, sizeof(reg), false,
					 &status);
#else
	rc = qm_ss_i2c_master_write(QM_SS_I2C_1, addr, &reg, sizeof(reg), false,
					 &status);
#endif
	if (rc != 0) {
		QM_PUTS("\t[Sensor] write_register1 Error!!!");
		QM_PRINTF("\t[Sensor] rc = %d\n", rc);
		return rc;
	}
#if (useI2C0)
	rc = qm_ss_i2c_master_write(QM_SS_I2C_0, addr, &data, sizeof(data), true,
					 &status);
#else
	rc = qm_ss_i2c_master_write(QM_SS_I2C_1, addr, &data, sizeof(data), true,
					 &status);
#endif
	if (rc != 0) {
		QM_PUTS("\t[Sensor] write_register2 Error!!!");
		QM_PRINTF("\t[Sensor] rc = %d\n", rc);
		return rc;
	}

	clk_sys_udelay(WRITE_WAIT_TIME_US);

	return 0;
}

void writeDataToMailBox(uint16_t tempData, uint16_t humidityData, uint16_t uvData)
{
	/* Register the interrupt handler. */
	//QM_IRQ_REQUEST(QM_IRQ_MAILBOX_0_INT, qm_mailbox_0_isr);

	tx_data.ctrl = 101;
	tx_data.data[0] = tempData;
	tx_data.data[1] = humidityData;
	tx_data.data[2] = uvData;

	if (0 != (unsigned int)qm_mbox_ch_write(SSmbox_tx_channel, &tx_data)) {
				QM_PRINTF("\t[Sensor] Error: mbox write error\n");
		}
}

bool CM3592_ReadUV(uint16_t *uv)
{
    bool success = false;
    uint8_t value[2]={0,0};
    uint16_t uvreal = 0;

    i2c_read_register(CM3592_I2C_ADDRESS, CM3592_UV_REG, value, sizeof(value));
    uvreal = value[1] << 8;
    uvreal += value[0];
    //QM_PRINTF("\t[Sensor] ReadUV = %d\n", uvreal);

    if(uvreal<747){
        uv[0] = 0;
    }else if(uvreal>=747 && uvreal<1494){
        uv[0] = 1;
    }else if(uvreal>=1494 && uvreal<2442){
        uv[0] = 2;
    }else if(uvreal>=2442 && uvreal<3188){
        uv[0] = 3;
    }else if(uvreal>=3188 && uvreal<3735){
        uv[0] = 4;
    }else if(uvreal>=3735 && uvreal<4483){
        uv[0] = 5;
    }else if(uvreal>=4483 && uvreal<5229){
        uv[0] = 6;
    }else if(uvreal>=5229 && uvreal<5977){
        uv[0] = 7;
    }else if(uvreal>=5977 && uvreal<6724){
        uv[0] = 8;
    }else if(uvreal>=6724 && uvreal<7471){
        uv[0] = 9;
    }else if(uvreal>=7471 && uvreal<8218){
        uv[0] = 10;
    }else{
        uv[0] = 10;
    }

    success = true;


    return(success);
}

bool CM3592_ReadUVB(uint16_t *uvb)
{
    bool success = false;
    uint8_t value[2]={0,0};
    uint16_t uvreal = 0;

    i2c_read_register(CM3592_I2C_ADDRESS, CM3592_UVB_REG, value, sizeof(value));
    uvreal = value[1] << 8;
    uvreal += value[0];
    QM_PRINTF("\t[Sensor] ReadUVB = %d\n", uvreal);

    if(uvreal<747){
        uvb[0] = 0;
    }else if(uvreal>=747 && uvreal<1494){
        uvb[0] = 1;
    }else if(uvreal>=1494 && uvreal<2442){
        uvb[0] = 2;
    }else if(uvreal>=2442 && uvreal<3188){
        uvb[0] = 3;
    }else if(uvreal>=3188 && uvreal<3735){
        uvb[0] = 4;
    }else if(uvreal>=3735 && uvreal<4483){
        uvb[0] = 5;
    }else if(uvreal>=4483 && uvreal<5229){
        uvb[0] = 6;
    }else if(uvreal>=5229 && uvreal<5977){
        uvb[0] = 7;
    }else if(uvreal>=5977 && uvreal<6724){
        uvb[0] = 8;
    }else if(uvreal>=6724 && uvreal<7471){
        uvb[0] = 9;
    }else if(uvreal>=7471 && uvreal<8218){
        uvb[0] = 10;
    }else{
        uvb[0] = 10;
    }

    success = true;


    return(success);
}


bool CM3592_ReadALS(uint16_t *als)
{
    bool success = false;
    uint8_t value[2]={0,0};

    i2c_read_register(CM3592_I2C_ADDRESS, CM3592_ALS_REG, value, sizeof(value));
    als[0] = value[1] << 8;
    als[0] += value[0];
    QM_PRINTF("\t[Sensor] ReadALS = %d\n", als[0]);

    success = true;


    return(success);
}

/* Mailbox callback on available data. */
void mbox_cb(void *callback_data)
{
	qm_mbox_ch_t *ch = (qm_mbox_ch_t *)callback_data;
	if (0 != qm_mbox_ch_read(*ch, &rx_data)) {
			QM_PRINTF("Error: Reading failed on mbox=%d, ctrl=%d.\n",
				       *ch, (int)rx_data.ctrl);
	}
	if(rx_data.data[0] == 0x01)
		QM_PUTS("\t[Sensor] A request from Core");

	QM_PUTS("\t[Sensor] MailBox call back fired, wake up from SS2.");

}

void MailBoxInit( void )
{
	//mboxInit
	rx_data.ctrl = 100;
	rx_data.data[0] = 0;
	rx_data.data[1] = 0;
	rx_data.data[2] = 0;
	rx_data.data[3] = 0;
	// Configure the mailbox for this channel
	// Register the interrupt handler.
	mbox_rx_config.dest = QM_MBOX_TO_SS;
	mbox_rx_config.mode = QM_MBOX_INTERRUPT_MODE;
	mbox_rx_config.callback = mbox_cb;
	mbox_rx_config.callback_data = NULL;

	/* Register the interrupt handler. */
	QM_IRQ_REQUEST(QM_IRQ_MAILBOX_0_INT, qm_mailbox_0_isr);

	/* Configure RX channel. */
	qm_mbox_ch_set_config(SSmbox_rx_channel, &mbox_rx_config);
}


//==///////
int main(void)
{
	int rc;
	test_counter = 0;
	iSUpdate_Data = false;
	qm_ss_i2c_config_t cfg;

	/*  Enable I2C 0 */
#if (useI2C0)
	ss_clk_i2c_enable(QM_SS_I2C_0);
#else
	ss_clk_i2c_enable(QM_SS_I2C_1);
#endif
	/* Configure I2C */
	cfg.address_mode = QM_SS_I2C_7_BIT;
	cfg.speed = QM_SS_I2C_SPEED_STD;

#if (useI2C0)
	if (qm_ss_i2c_set_config(QM_SS_I2C_0, &cfg)) {
			QM_PUTS("Error: I2C_SS_0 config\n");
		}
#else
	if (qm_ss_i2c_set_config(QM_SS_I2C_1, &cfg)) {
			QM_PUTS("Error: I2C_SS_1 config\n");
		}
#endif

	/* CM3592 initialise */
	uint8_t CM3592_init[2];
	CM3592_init[0] = 0x00;
	CM3592_init[1] = 0x0;
	i2c_write_register(CM3592_I2C_ADDRESS, CM3592_CONGFIG_REG, CM3592_init[0]);

	uint16_t last_temp_result, last_humidity_result;
	uint16_t last_uv_result;
	last_temp_result     = 0;
	last_humidity_result = 0;
	last_uv_result = 0;

	MailBoxInit();
	while(1){
		QM_PUTS("\t==================================================");

	uint8_t temp_data[2];
	rc = i2c_read_register(SHT21_ADDR, eTempHoldCmd, temp_data, sizeof(temp_data));
	if (0 != rc) {
		QM_PRINTF("\t[Sensor] Error: Can not Read Temperature Data\n");
	}

	uint16_t result, result_tm;
	result = temp_data[0];
	result = result << 8;

	i2c_read_register(SHT21_ADDR, eTempHoldCmd, temp_data, sizeof(temp_data)); //
	result_tm = temp_data[0];                                                  //
	result += result_tm;                                                       //
	result &= ~0x0003;
	result = -46.85 + 175.72 / 65536.0 * (float)(result);
	//QM_PRINTF("\t[Sensor] Temperature(C) = %d\n", result);
	if(last_temp_result != result)
	{
		last_temp_result = result;
		QM_PRINTF("\t[Sensor] Temperature(C) = %d\n", result);
		if(iSUpdate_Data == false)
		{
			iSUpdate_Data = true;
		}
	}

	uint8_t humidity_data[2];
	rc = i2c_read_register(SHT21_ADDR, eRHumidityHoldCmd, humidity_data, sizeof(humidity_data));
	if (0 != rc) {
			QM_PRINTF("\t[Sensor] Error: Can not Read Humidity Data\n");
	}
	uint16_t result1, result1_tm;
	result1 = humidity_data[0];
	result1 = result1 << 8;

	i2c_read_register(SHT21_ADDR, eRHumidityHoldCmd, humidity_data, sizeof(humidity_data)); //
	result1_tm = humidity_data[0];                                                          //
	result1 += result1_tm;                                                                  //
                                              //
	result1 &= ~0x0003;
	result1 = -6.0 + 125.0 / 65536.0 * (float)(result1);
	//QM_PRINTF("\t[Sensor] Humidity(%RH) = %d\n", result1);
	if(last_humidity_result != result1)
	{
		QM_PRINTF("\t[Sensor] Humidity(%RH) = %d\n", result1);
		last_humidity_result = result1;
		if(iSUpdate_Data == false)
		{
			iSUpdate_Data = true;
		}
	}

	uint16_t result2=0;

//	CM3592_ReadUVB(&result2);
//		QM_PRINTF("UVB = %d\n", result2);
//	CM3592_ReadALS(&result2);
//		QM_PRINTF("ALS = %d\n", result2);
	CM3592_ReadUV(&result2);
//	QM_PRINTF("\t[Sensor] UV = %d\n", result2);
	//CM3592_ReadUVB(&result2);
	//QM_PRINTF("UVB = %d\n", result2);
	//CM3592_ReadALS(&result2);
	//QM_PRINTF("ALS = %d\n", result2);

	if(last_uv_result != result2)
	{
		QM_PRINTF("\t[Sensor] UV = %d\n", result2);
		last_uv_result = result2;
		if(iSUpdate_Data == false)
		{
			iSUpdate_Data = true;
		}
	}

	if(iSUpdate_Data)
	{
		writeDataToMailBox(last_temp_result,last_humidity_result,last_uv_result);
		iSUpdate_Data = false;
	}
	clk_sys_udelay(1000000);


	//QM_PUTS("Go to ss2.");
	/* Go to SS2, Timer will wake. */
	//qm_ss_power_cpu_ss2();

	}

	return 0;
}
