/*
 * Main_User.c
 *
 * Created  : 23 July 2021
 * Modified : 27 July 2021
 * Author   : HWanyusof
 * Version	: 1.1
 */

#include "usbd_cdc_if.h"
#include "string.h"
#include "stm32f4xx_hal.h"
#include "VCNL4030X01.h"
#include "VCNL4030X01_Prototypes.h"
#include "typedefinition.h"
#include "VCNL4030X01_Application_Library.h"
#include "Main_User.h"


//Global Variables

//Switch the I2C Bus number here (Currently only tested with Teensy3.5 with possibility to use multiple i2c channels)
// I2C_Bus = 1 for Wire 1 (Pin 18-SDA, 19-SCL)
// I2C_Bus = 2 for Wire 2 (Pin 37-SCL, 38-SDA)
//Other Arduino family boards-please use I2C_Bus = 1
//Other platforms will not be affected
int I2C_Bus = 2;

//Variables for Offset Value
int CalibValue = 0;
int AverageCount = 10; //Change the average count to the needed number of offset measurement

void INIT_VCNL4030X01()
{
	/* Reset Sensor to default value */
	Reset_Sensor();

	/****************************************************************************/
	/****************************Basic  Initialization***************************/
	/*
     *Basic_Initialization_Auto_Mode() uses the most basic steps to turn on the Proximity Sensor.
     *Very useful when first working with the sensor.
     *For the more advanced settings, you can use the Auto_Mode(), AF_Mode(),
     *Low_Power_Mode(), ALS_Mode() and White_Mode() functions.
     */

	//Basic_Initialization_Auto_Mode();
	White_Mode();

	/***************************End of Initialization****************************/
    /****************************************************************************/
}

//Print Function
void PRINT_VCNL4030X01()
{
	/*
     *If you are using Basic_Initialization_Auto_Mode() to turn on the Proximity Sensor,
     *you can use Print_Data_Only() to read the proximity sensor.
     *If you are using more advanced settings like Auto_Mode(), AF_Mode(),
     *Low_Power_Mode(), ALS_Mode() and White_Mode() functions, you can use all of the print functions :
     *Print_Data_Only() or Print_All().
     */

	/* Print the sensor output */
	//Print_Data_Only();
	Print_All();
}

//Auto/Self-Timed Mode Basic Initialization Function
void Basic_Initialization_Auto_Mode()
{
    //1.) Initialization
    //Disable the PS
    VCNL4030X01_SET_PS_SD(VCNL4030X01_PS_SD_DIS);
    //Setting up Auto Mode
    VCNL4030X01_SET_PS_AF(VCNL4030X01_PS_AUTO);
    //PS_SD will be set after all of the parameters have been set up

    //2.) Setting up PS
    //PS_CONF1
    //Set the Integration Time
    VCNL4030X01_SET_PS_IT(VCNL4030X01_PS_IT_8T);

    //PS_CONF2
    //Set the Output Bit Size
    VCNL4030X01_SET_PS_HD(VCNL4030X01_PS_HD_16Bits);

    //PS_CONF3
    //Enable/Disable Sunlight Cancellation
    VCNL4030X01_SET_PS_SC_EN(VCNL4030X01_PS_SC_EN);

    //PS_MS
    //Set the LED Current
    VCNL4030X01_SET_PS_LED_I(VCNL4030X01_PS_LED_I_200mA);

    //3.) Switch On the sensor
    VCNL4030X01_SET_PS_SD(VCNL4030X01_PS_SD_EN);

    //Delay needs to be changed depending on the API of the µ-controller
	HAL_Delay(1000);
}

//White Mode Initialization Function
void White_Mode()
{
    //1.)Initialization
    //Switch Off the ALS
    VCNL4030X01_SET_ALS_SD(VCNL4030X01_ALS_SD_DIS);
    //Disable White Channel
    VCNL4030X01_SET_WHITE_SD(VCNL4030X01_ALS_WHITE_SD_DIS);

    //2.) Setting up White Channel
    //Can use some of the ALS channel parameters
    //ALS_CONF1
    //Set the ALS Integration Time
    VCNL4030X01_SET_ALS_IT(VCNL4030X01_ALS_IT_50MS);


    //3.) Switch On the White and ALS Channel
    VCNL4030X01_SET_ALS_SD(VCNL4030X01_ALS_SD_EN);
    VCNL4030X01_SET_WHITE_SD(VCNL4030X01_ALS_WHITE_SD_EN);

    HAL_Delay(1000);
}

//ALS Mode Initialization Function
void ALS_Mode()
{
    //1.) Initialization
    //Switch Off the ALS
    VCNL4030X01_SET_ALS_SD(VCNL4030X01_ALS_SD_DIS);
    //Enable/Disable White Channel (Disable for normal ALS wavelength)
    VCNL4030X01_SET_WHITE_SD(VCNL4030X01_ALS_WHITE_SD_DIS);

    //2.) Setting up ALS
    //ALS_CONF1
    //Enable/Disable Interrupt
    VCNL4030X01_SET_ALS_Interrupt(VCNL4030X01_ALS_INT_EN);
    //Set the Persistence of the Ambient Light Sensor
    VCNL4030X01_SET_ALS_PERS(VCNL4030X01_ALS_PERS_1);
    //Set the Dynamic Range
    VCNL4030X01_SET_ALS_HD(VCNL4030X01_ALS_HD_X1);
    //Set the ALS Integration Time
    VCNL4030X01_SET_ALS_IT(VCNL4030X01_ALS_IT_50MS);

    //ALS_CONF2
    //Set the ALS Sensitivity
    VCNL4030X01_SET_ALS_NS(VCNL4030X01_ALS_NS_X2);

    //ALS_THDH
    //Set the ALS Interrupt Higher Threshold
    VCNL4030X01_SET_ALS_HighThreshold(5000);

    //ALS_THDL
    //Set the ALS Interrupt Lower Threshold
    VCNL4030X01_SET_ALS_LowThreshold(3000);

    //3.) Switch On the ALS
    VCNL4030X01_SET_ALS_SD(VCNL4030X01_ALS_SD_EN);

    //Clear Initial Interrupt
    VCNL4030X01_GET_PS_Interrupt();

    HAL_Delay(1000);
}

//Low Power Mode Initialization Function
void Low_Power_Mode()
{
    //1.) Initialization
    //Disable the PS
    VCNL4030X01_SET_PS_SD(VCNL4030X01_PS_SD_DIS);
    //Setting up Auto Mode
    VCNL4030X01_SET_PS_AF(VCNL4030X01_PS_AUTO);
    //PS_SD will be set before measuring the offset or after all of the parameters have been set up

    //2.) Setting up PS
    //PS_CONF1
    //Set the PS IRED on/off Duty Ratio setting
    VCNL4030X01_SET_PS_DUTY(VCNL4030X01_PS_DR_1_40);
    //Set the Persistence
    VCNL4030X01_SET_PS_PERS(VCNL4030X01_PS_PERS_1);
    //Set the Integration Time
    VCNL4030X01_SET_PS_IT(VCNL4030X01_PS_IT_8T);

    //PS_CONF2
    //Set the Gain
    //Recommended to use VCNL4030X01_PS_GAIN_2_STEP
    VCNL4030X01_SET_PS_Gain(VCNL4030X01_PS_GAIN_2_STEP);
    //Set the Output Bit Size
    VCNL4030X01_SET_PS_HD(VCNL4030X01_PS_HD_16Bits);
    //Set the Sensitivity Mode
    //Recommended to use VCNL4030X01_PS_NS_2STEP_MODE_X4
    VCNL4030X01_SET_PS_NS(VCNL4030X01_PS_NS_2STEP_MODE_X4);
    //Set the Interrupt
    VCNL4030X01_SET_PS_INT(VCNL4030X01_PS_INT_CLOSE_AWAY);

    //PS_CONF3
    //Enable/Disable Low Current
    //When enabled -  1/10 of normal current,
    //with that the current is accordingly: 5 mA, 7.5 mA, 10 mA, 12 mA, 14 mA, 16 mA, 18 mA, 20 mA.
    //The current in VCNL4030X01_SET_PS_LED_I() still has to be set and the value will be 1/10 of that.
    VCNL4030X01_SET_PS_LED_I_LOW(VCNL4030X01_PS_I_LOW_EN);
    //Enable/Disable Smart Persistence
    VCNL4030X01_SET_PS_SMART_PERS(VCNL4030X01_PS_SMART_PERS_DIS);
    //Set Interrupt to Normal/Logic Mode
    VCNL4030X01_SET_PS_MS(VCNL4030X01_PS_MS_NORMAL);
    //Enable/Disable Sunlight Cancellation
    VCNL4030X01_SET_PS_SC_EN(VCNL4030X01_PS_SC_EN);
    //PS_AF has been set during initialization

    //PS_MS
    //Set the Sunlight Cancellation Current
    VCNL4030X01_SET_PS_SC_CUR(VCNL4030X01_PS_SC_CURx1);
    //Set the Sunlight Capability
    VCNL4030X01_SET_PS_SP(VCNL4030X01_PS_SPx1);
    //Set the Output of Sunlight Protect Mode
    VCNL4030X01_SET_PS_SPO(VCNL4030X01_PS_SPO_00);
    //Set the LED Current
    VCNL4030X01_SET_PS_LED_I(VCNL4030X01_PS_LED_I_200mA);

    //3.) Switch On the sensor
    VCNL4030X01_SET_PS_SD(VCNL4030X01_PS_SD_EN);
    //Delay of 10 ms needs to be changed depending on the API of the µ-controller of use
    HAL_Delay(10);

    //Clear Initial Interrupt
    VCNL4030X01_GET_PS_Interrupt();
    HAL_Delay(10);

	//4.) Threshold Setting and Offset Measurement
	for(int i=0;i<AverageCount;i++)
	{
		CalibValue += VCNL4030X01_GET_PS_Data();
		//Delay of 10 ms needs to be changed depending on the API of the µ-controller of use
		HAL_Delay(10);
	}

	//Calculate the average of the offset measurement
	CalibValue /= AverageCount;

	//Set Cancellation register to eliminate offset
	VCNL4030X01_SET_PS_CANC(CalibValue);
	//Set Low Threshold
	VCNL4030X01_SET_PS_LowThreshold(3000);
	//set High Threshold
	VCNL4030X01_SET_PS_HighThreshold(5000);

    HAL_Delay(1000);
}

//AF/Continuous Forced Mode Initialization Function
void AF_Mode()
{
    //1.) Initialization
    //Disable the PS
    VCNL4030X01_SET_PS_SD(VCNL4030X01_PS_SD_DIS);
    //Setting up AF Mode
    VCNL4030X01_SET_PS_AF(VCNL4030X01_PS_AF_EN);
    //PS_SD will be set before measuring the offset or after all of the parameters have been set up

    //2.) Setting up PS
    //PS_CONF1
    //PS_DUTY does not play a role in AF Mode
    //Set the Persistence
    VCNL4030X01_SET_PS_PERS(VCNL4030X01_PS_PERS_1);
    //Set the Integration Time
    VCNL4030X01_SET_PS_IT(VCNL4030X01_PS_IT_8T);

    //PS_CONF2
    //Set the Gain
    //Recommended to use VCNL4030X01_PS_GAIN_2_STEP
    VCNL4030X01_SET_PS_Gain(VCNL4030X01_PS_GAIN_2_STEP);
    //Set the Output Bit Size
    VCNL4030X01_SET_PS_HD(VCNL4030X01_PS_HD_16Bits);
    //Set the Sensitivity Mode
    //Recommended to use VCNL4030X01_PS_NS_2STEP_MODE_X4
    VCNL4030X01_SET_PS_NS(VCNL4030X01_PS_NS_2STEP_MODE_X4);
    //Set the Interrupt
    VCNL4030X01_SET_PS_INT(VCNL4030X01_PS_INT_CLOSE_AWAY);

    //PS_CONF3
    //Enable/Disable Low Current
    VCNL4030X01_SET_PS_LED_I_LOW(VCNL4030X01_PS_I_LOW_DIS);
    //Enable/Disable Smart Persistence
    VCNL4030X01_SET_PS_SMART_PERS(VCNL4030X01_PS_SMART_PERS_DIS);
    //Set Interrupt to Normal/Logic Mode
    VCNL4030X01_SET_PS_MS(VCNL4030X01_PS_MS_NORMAL);
    //Enable/Disable Sunlight Cancellation
    VCNL4030X01_SET_PS_SC_EN(VCNL4030X01_PS_SC_EN);
    //PS_AF has been set during initialization
    //PS_TRIG must be set before reading the proximity data

    //PS_MS
    //Set the Sunlight Cancellation Current
    VCNL4030X01_SET_PS_SC_CUR(VCNL4030X01_PS_SC_CURx1);
    //Set the Sunlight Capability
    VCNL4030X01_SET_PS_SP(VCNL4030X01_PS_SPx1);
    //Set the Output of Sunlight Protect Mode
    VCNL4030X01_SET_PS_SPO(VCNL4030X01_PS_SPO_00);
    //Set the LED Current
    VCNL4030X01_SET_PS_LED_I(VCNL4030X01_PS_LED_I_200mA);

    //3.) Switch On the sensor
    VCNL4030X01_SET_PS_SD(VCNL4030X01_PS_SD_EN);
    //Delay of 10 ms needs to be changed depending on the API of the µ-controller of use
    HAL_Delay(10);

    //Clear Initial Interrupt
    VCNL4030X01_GET_PS_Interrupt();
    HAL_Delay(10);

	//4.) Threshold Setting and Offset Measurement
	for(int i=0;i<AverageCount;i++)
	{
		//Enable trigger to start offset measurement
		VCNL4030X01_SET_PS_TRIG(VCNL4030X01_PS_TRIG_EN);
		//Delay of 10 ms needs to be changed depending on the API of the µ-controller of use
		HAL_Delay(10);
		CalibValue += VCNL4030X01_GET_PS_Data();
		//Delay of 10 ms needs to be changed depending on the API of the µ-controller of use
		HAL_Delay(10);
	}

	//Calculate the average of the offset measurement
	CalibValue /= AverageCount;

	//Set Cancellation register to eliminate offset
	VCNL4030X01_SET_PS_CANC(CalibValue);
	//Set Low Threshold
	VCNL4030X01_SET_PS_LowThreshold(3000);
	//set High Threshold
	VCNL4030X01_SET_PS_HighThreshold(5000);

    HAL_Delay(1000);
}

//Auto/Self-Timed Mode Initialization Function
void Auto_Mode()
{
    //1.) Initialization
    //Disable the PS
    VCNL4030X01_SET_PS_SD(VCNL4030X01_PS_SD_DIS);
    //Setting up Auto Mode
    VCNL4030X01_SET_PS_AF(VCNL4030X01_PS_AUTO);
    //PS_SD will be set before measuring the offset or after all of the parameters have been set up

    //2.) Setting up PS
    //PS_CONF1
    //Set the PS IRED on/off Duty Ratio setting
    VCNL4030X01_SET_PS_DUTY(VCNL4030X01_PS_DR_1_40);
    //Set the Persistence
    VCNL4030X01_SET_PS_PERS(VCNL4030X01_PS_PERS_1);
    //Set the Integration Time
    VCNL4030X01_SET_PS_IT(VCNL4030X01_PS_IT_8T);

    //PS_CONF2
    //Set the Gain
    //Recommended to use VCNL4030X01_PS_GAIN_2_STEP
    VCNL4030X01_SET_PS_Gain(VCNL4030X01_PS_GAIN_2_STEP);
    //Set the Output Bit Size
    VCNL4030X01_SET_PS_HD(VCNL4030X01_PS_HD_16Bits);
    //Set the Sensitivity Mode
    //Recommended to use VCNL4030X01_PS_NS_2STEP_MODE_X4
    VCNL4030X01_SET_PS_NS(VCNL4030X01_PS_NS_2STEP_MODE_X4);
    //Set the Interrupt
    VCNL4030X01_SET_PS_INT(VCNL4030X01_PS_INT_CLOSE_AWAY);

    //PS_CONF3
    //Enable/Disable Low Current
    VCNL4030X01_SET_PS_LED_I_LOW(VCNL4030X01_PS_I_LOW_DIS);
    //Enable/Disable Smart Persistence
    VCNL4030X01_SET_PS_SMART_PERS(VCNL4030X01_PS_SMART_PERS_DIS);
    //Set Interrupt to Normal/Logic Mode
    VCNL4030X01_SET_PS_MS(VCNL4030X01_PS_MS_NORMAL);
    //Enable/Disable Sunlight Cancellation
    VCNL4030X01_SET_PS_SC_EN(VCNL4030X01_PS_SC_EN);
    //PS_AF has been set during initialization

    //PS_MS
    //Set the Sunlight Cancellation Current
    VCNL4030X01_SET_PS_SC_CUR(VCNL4030X01_PS_SC_CURx1);
    //Set the Sunlight Capability
    VCNL4030X01_SET_PS_SP(VCNL4030X01_PS_SPx1);
    //Set the Output of Sunlight Protect Mode
    VCNL4030X01_SET_PS_SPO(VCNL4030X01_PS_SPO_00);
    //Set the LED Current
    VCNL4030X01_SET_PS_LED_I(VCNL4030X01_PS_LED_I_200mA);

    //3.) Switch On the sensor
    VCNL4030X01_SET_PS_SD(VCNL4030X01_PS_SD_EN);
    //Delay of 10 ms needs to be changed depending on the API of the µ-controller of use
    HAL_Delay(10);

    //Clear Initial Interrupt
    VCNL4030X01_GET_PS_Interrupt();
    HAL_Delay(10);

	//4.) Threshold Setting and Offset Measurement
	for(int i=0;i<AverageCount;i++)
	{
		CalibValue += VCNL4030X01_GET_PS_Data();
		//Delay of 10 ms needs to be changed depending on the API of the µ-controller of use
		HAL_Delay(10);
	}

	//Calculate the average of the offset measurement
	CalibValue /= AverageCount;

	//Set Cancellation register to eliminate offset
	VCNL4030X01_SET_PS_CANC(CalibValue);
	//Set Low Threshold
	VCNL4030X01_SET_PS_LowThreshold(3000);
	//set High Threshold
	VCNL4030X01_SET_PS_HighThreshold(5000);

	HAL_Delay(1000);
}
