//*****************************************************************************
//
// This task captures data from the ISL29023 sensor and puts it into the shared
// data structure.
//
//*****************************************************************************
static void
ISL29023Task(void *pvParameters)
{
    portTickType xLastWakeTime;
    float fVisible;
    uint8_t ui8Mask;

    //
    // The binary semaphore is created full so we empty it first so we can
    // use it to wait for the AppCallback function.
    //
    xSemaphoreTake(g_xISL29023TransactionCompleteSemaphore, 0);
    xSemaphoreTake(g_xISL29023AdjustRangeSemaphore, 0);

    //
    // Take the I2C semaphore so we can init the sensor. Keep it until all init
    // is complete for this sensor.
    //
    xSemaphoreTake(g_xI2CSemaphore, portMAX_DELAY);

    //
    // Initialize the ISL29023 Driver.
    //
    ISL29023Init(&g_sISL29023Inst, &g_sI2CInst, ISL29023_I2C_ADDRESS,
                 ISL29023AppCallback, &g_sISL29023Inst);

    //
    // Wait for transaction to complete
    //
    xSemaphoreTake(g_xISL29023TransactionCompleteSemaphore, portMAX_DELAY);

    //
    // If an error occurred call the error handler immediately.
    //
    if(g_vui8ISL29023I2CErrorStatus)
    {
        //
        // Give back the I2C Semaphore
        //
        xSemaphoreGive(g_xI2CSemaphore);

        //
        // Call the error handler.
        //
        ISL29023AppErrorHandler(__FILE__, __LINE__);
    }

    //
    // Configure the ISL29023 to measure Visible light continuously. Set a 8
    // sample persistence before the INT pin is asserted. Clears the INT flag.
    // Persistence setting of 8 is sufficient to ignore camera flashes.
    //
    ui8Mask = (ISL29023_CMD_I_OP_MODE_M | ISL29023_CMD_I_INT_PERSIST_M |
               ISL29023_CMD_I_INT_FLAG_M);
    ISL29023ReadModifyWrite(&g_sISL29023Inst, ISL29023_O_CMD_I, ~ui8Mask,
                            (ISL29023_CMD_I_OP_MODE_ALS_CONT |
                             ISL29023_CMD_I_INT_PERSIST_8),
                            ISL29023AppCallback, &g_sISL29023Inst);

    //
    // Wait for transaction to complete
    //
    xSemaphoreTake(g_xISL29023TransactionCompleteSemaphore, portMAX_DELAY);

    //
    // If an error occurred call the error handler immediately.
    //
    if(g_vui8ISL29023I2CErrorStatus)
    {
        //
        // Give back the I2C Semaphore
        //
        xSemaphoreGive(g_xI2CSemaphore);

        //
        // Call the Error handler.
        //
        ISL29023AppErrorHandler(__FILE__, __LINE__);
    }

    //
    // Configure the upper threshold to 80% of maximum value
    //
    g_sISL29023Inst.pui8Data[1] = 0xCC;
    g_sISL29023Inst.pui8Data[2] = 0xCC;
    ISL29023Write(&g_sISL29023Inst, ISL29023_O_INT_HT_LSB,
                  g_sISL29023Inst.pui8Data, 2, ISL29023AppCallback,
                  &g_sISL29023Inst);

    //
    // Wait for transaction to complete
    //
    xSemaphoreTake(g_xISL29023TransactionCompleteSemaphore, portMAX_DELAY);

    //
    // If an error occurred call the error handler immediately.
    //
    if(g_vui8ISL29023I2CErrorStatus)
    {
        //
        // Give back the I2C Semaphore
        //
        xSemaphoreGive(g_xI2CSemaphore);

        //
        // Call the error handler.
        //
        ISL29023AppErrorHandler(__FILE__, __LINE__);
    }

    //
    // Configure the lower threshold to 20% of maximum value
    //
    g_sISL29023Inst.pui8Data[1] = 0x33;
    g_sISL29023Inst.pui8Data[2] = 0x33;
    ISL29023Write(&g_sISL29023Inst, ISL29023_O_INT_LT_LSB,
                  g_sISL29023Inst.pui8Data, 2, ISL29023AppCallback,
                  &g_sISL29023Inst);

    //
    // Wait for transaction to complete
    //
    xSemaphoreTake(g_xISL29023TransactionCompleteSemaphore, portMAX_DELAY);

    //
    // Give back the I2C Semaphore
    //
    xSemaphoreGive(g_xI2CSemaphore);

    //
    // If an error occurred call the error handler immediately.
    //
    if(g_vui8ISL29023I2CErrorStatus)
    {
        ISL29023AppErrorHandler(__FILE__, __LINE__);
    }

    //
    // Get the current time as a reference to start our delays.
    //
    xLastWakeTime = xTaskGetTickCount();

    //
    // Loop forever.
    //
    while(1)
    {
        //
        // Wait for the required amount of time to check back.
        //
        vTaskDelayUntil(&xLastWakeTime, ISL29023_TASK_PERIOD_MS /
                                        portTICK_RATE_MS);

        //
        // Take the I2C semaphore.  Given back in the Interrupt contect in the
        // callback function after I2C transaction is complete.
        //
        xSemaphoreTake(g_xI2CSemaphore, portMAX_DELAY);

        //
        // Go get the latest data from the sensor.
        //
        ISL29023DataRead(&g_sISL29023Inst, ISL29023AppCallback,
                         &g_sISL29023Inst);

        //
        // Wait for the I2C Driver to tell us that transaction is complete.
        //
        xSemaphoreTake(g_xISL29023TransactionCompleteSemaphore, portMAX_DELAY);

        //
        // Give back the I2C Semaphore so other can use the I2C interface.
        //
        xSemaphoreGive(g_xI2CSemaphore);

        //
        // If an error occurred call the error handler immediately.
        //
        if(g_vui8ISL29023I2CErrorStatus)
        {
            ISL29023AppErrorHandler(__FILE__, __LINE__);
        }

        //
        // Get a local floating point copy of the latest light data
        //
        ISL29023DataLightVisibleGetFloat(&g_sISL29023Inst, &fVisible);

        //
        // Check if the intensity of light has crossed a threshold. If so
        // then adjust range of sensor readings to track intensity.
        //
        if(xSemaphoreTake(g_xISL29023AdjustRangeSemaphore, 0) == pdTRUE)
        {
            //
            // Adjust the lux range.
            //
            ISL29023AppAdjustRange(fVisible);

            //
            // Take the I2C semaphore.  Given back in the Interrupt contect in
            // the callback function after I2C transaction is complete.
            //
            xSemaphoreTake(g_xI2CSemaphore, portMAX_DELAY);

            //
            // Now we must manually clear the flag in the ISL29023
            // register.
            //
            ISL29023Read(&g_sISL29023Inst, ISL29023_O_CMD_I,
                         g_sISL29023Inst.pui8Data, 1, ISL29023AppCallback,
                         &g_sISL29023Inst);

            //
            // Wait for the I2C Driver to tell us that transaction is complete.
            //
            xSemaphoreTake(g_xISL29023TransactionCompleteSemaphore,
                           portMAX_DELAY);

            //
            // Give back the I2C Semaphore so other can use the I2C interface.
            //
            xSemaphoreGive(g_xI2CSemaphore);

            //
            // If an error occurred call the error handler immediately.
            //
            if(g_vui8ISL29023I2CErrorStatus)
            {
                ISL29023AppErrorHandler(__FILE__, __LINE__);
            }
        }

        //
        // Publish the data to the global structure for consumption by other
        // tasks.
        //
        xSemaphoreTake(g_xCloudDataSemaphore, portMAX_DELAY);
        g_sISL29023Data.fVisible = fVisible;
        g_sISL29023Data.xTimeStampTicks = xTaskGetTickCount();
        g_sISL29023Data.ui8Range = g_sISL29023Inst.ui8Range;
        xSemaphoreGive(g_xCloudDataSemaphore);

    }
}
void ISL29023AppCallback(void *pvCallbackData, unsigned     int ui8Status)
{
	
		float fAmbient;
    
		unsigned char tempString[30]={0};
		
		float tempfAmbient;
		uint8_t ui8NewRange;
		
		if(ui8Status == I2CM_STATUS_SUCCESS&&sensorTurn==2)
		{
				//
				// Get a local floating point copy of the latest light data
				//
				ISL29023DataLightVisibleGetFloat(&g_sISL29023Inst, &fAmbient);
			
				//
				// Perform the conversion from float to a printable set of integers
				//
				ISL290_i32IntegerPart = (int32_t)fAmbient;
				ISL290_i32FractionPart = (int32_t)(fAmbient * 1000.0f);
				ISL290_i32FractionPart = ISL290_i32FractionPart - (ISL290_i32IntegerPart * 1000);
				if(ISL290_i32FractionPart < 0)
				{
						ISL290_i32FractionPart *= -1;
				}

				//
				// Print the temperature as integer and fraction parts.
				//
				//sprintf(tempString,"Visible Lux: %3d.%03d\n\r", ISL290_i32IntegerPart,ISL290_i32FractionPart);
				//CLI_Write(tempString);

				if(g_vui8IntensityFlag)
				{
					IntPriorityMaskSet(0x40);
					//
					// Reset the intensity trigger flag.
					//
					g_vui8IntensityFlag = 0;

					//
					// Adjust the lux range.
					//
					
					ui8NewRange = g_sISL29023Inst.ui8Range;

					//
					// Get a local floating point copy of the latest light data
					//
					ISL29023DataLightVisibleGetFloat(&g_sISL29023Inst, &tempfAmbient);

					//
					// Check if we crossed the upper threshold.
					//
					if(tempfAmbient > g_fThresholdHigh[g_sISL29023Inst.ui8Range])
					{
							//
							// The current intensity is over our threshold so adjsut the range
							// accordingly
							//
							if(g_sISL29023Inst.ui8Range < ISL29023_CMD_II_RANGE_64K)
							{
									ui8NewRange = g_sISL29023Inst.ui8Range + 1;
							}
					}

					//
					// Check if we crossed the lower threshold
					//
					if(tempfAmbient < g_fThresholdLow[g_sISL29023Inst.ui8Range])
					{
							//
							// If possible go to the next lower range setting and reconfig the
							// thresholds.
							//
							if(g_sISL29023Inst.ui8Range > ISL29023_CMD_II_RANGE_1K)
							{
									ui8NewRange = g_sISL29023Inst.ui8Range - 1;
							}
					}
					
					//
					// If the desired range value changed then send the new range to the sensor
					//
					if(ui8NewRange != g_sISL29023Inst.ui8Range)
					{
							ISL29023ReadModifyWrite(&g_sISL29023Inst, ISL29023_O_CMD_II,
																			~ISL29023_CMD_II_RANGE_M, ui8NewRange,
																			ISL29023AppCallback, &g_sISL29023Inst);
					}
					
					SysCtlDelay(g_SysClock / (100 * 3));
					//
					// Now we must manually clear the flag in the ISL29023
					// register.
					//
					ISL29023Read(&g_sISL29023Inst, ISL29023_O_CMD_I,
											 g_sISL29023Inst.pui8Data, 1, ISL29023AppCallback,
											 &g_sISL29023Inst);

					//
					// Wait for transaction to complete
					//
					SysCtlDelay(g_SysClock / (100 * 3));
					
					//
					// Disable priority masking so all interrupts are enabled.
					//
					
					IntPriorityMaskSet(0);
				}
				sensorTurn=(sensorTurn+1)%NumberOfSensor;
				TimerEnable(TIMER1_BASE, TIMER_A);
		}
		
}
//*****************************************************************************
//
// Main 'C' Language entry point.
//
//*****************************************************************************
int
main(void)
{
    float fAmbient;
    int32_t i32IntegerPart, i32FractionPart;
    uint8_t ui8Mask;

    //
    // Setup the system clock to run at 40 Mhz from PLL with crystal reference
    //
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
                       SYSCTL_OSC_MAIN);

    //
    // Enable the peripherals used by this example.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

    //
    // Initialize the UART and its pins.
    //
    ConfigureUART();

    //
    // Print the welcome message to the terminal.
    //
    UARTprintf("\033[2JISL29023 Example\n");

    //
    // Set the color to a white approximation.
    //
    g_pui32Colors[RED] = 0x8000;
    g_pui32Colors[BLUE] = 0x8000;
    g_pui32Colors[GREEN] = 0x8000;

    //
    // Initialize RGB driver. Use a default intensity and blink rate.
    //
    RGBInit(0);
    RGBColorSet(g_pui32Colors);
    RGBIntensitySet(0.5f);
    RGBEnable();

    //
    // The I2C3 peripheral must be enabled before use.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C3);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);

    //
    // Configure the pin muxing for I2C3 functions on port D0 and D1.
    // This step is not necessary if your part does not support pin muxing.
    //
    ROM_GPIOPinConfigure(GPIO_PD0_I2C3SCL);
    ROM_GPIOPinConfigure(GPIO_PD1_I2C3SDA);

    //
    // Select the I2C function for these pins.  This function will also
    // configure the GPIO pins pins for I2C operation, setting them to
    // open-drain operation with weak pull-ups.  Consult the data sheet
    // to see which functions are allocated per pin.
    //
    GPIOPinTypeI2CSCL(GPIO_PORTD_BASE, GPIO_PIN_0);
    ROM_GPIOPinTypeI2C(GPIO_PORTD_BASE, GPIO_PIN_1);

    //
    // Configure and Enable the GPIO interrupt. Used for INT signal from the
    // ISL29023
    //
    ROM_GPIOPinTypeGPIOInput(GPIO_PORTE_BASE, GPIO_PIN_5);
    GPIOIntEnable(GPIO_PORTE_BASE, GPIO_PIN_5);
    ROM_GPIOIntTypeSet(GPIO_PORTE_BASE, GPIO_PIN_5, GPIO_FALLING_EDGE);
    ROM_IntEnable(INT_GPIOE);

    //
    // Keep only some parts of the systems running while in sleep mode.
    // GPIOE is for the ISL29023 interrupt pin.
    // UART0 is the virtual serial port
    // TIMER0, TIMER1 and WTIMER5 are used by the RGB driver
    // I2C3 is the I2C interface to the ISL29023
    //
    ROM_SysCtlPeripheralClockGating(true);
    ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOE);
    ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART0);
    ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_TIMER0);
    ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_TIMER1);
    ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_I2C3);
    ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_WTIMER5);

    //
    // Configure desired interrupt priorities.  Setting the I2C interrupt to be
    // of more priority than SysTick and the GPIO interrupt means those
    // interrupt routines can use the I2CM_DRV Application context does not use
    // I2CM_DRV API and GPIO and SysTick are at the same priority level. This
    // prevents re-entrancy problems with I2CM_DRV but keeps the MCU in sleep
    // state as much as possible. UART is at least priority so it can operate
    // in the background.
    //
    ROM_IntPrioritySet(INT_I2C3, 0x00);
    ROM_IntPrioritySet(FAULT_SYSTICK, 0x40);
    ROM_IntPrioritySet(INT_GPIOE, 0x80);
    ROM_IntPrioritySet(INT_UART0, 0x80);

    //
    // Enable interrupts to the processor.
    //
    ROM_IntMasterEnable();

    //
    // Initialize I2C3 peripheral.
    //
    I2CMInit(&g_sI2CInst, I2C3_BASE, INT_I2C3, 0xff, 0xff,
             ROM_SysCtlClockGet());

    //
    // Initialize the ISL29023 Driver.
    //
    ISL29023Init(&g_sISL29023Inst, &g_sI2CInst, ISL29023_I2C_ADDRESS,
                 ISL29023AppCallback, &g_sISL29023Inst);

    //
    // Wait for transaction to complete
    //
    ISL29023AppI2CWait(__FILE__, __LINE__);

    //
    // Configure the ISL29023 to measure ambient light continuously. Set a 8
    // sample persistence before the INT pin is asserted. Clears the INT flag.
    // Persistence setting of 8 is sufficient to ignore camera flashes.
    //
    ui8Mask = (ISL29023_CMD_I_OP_MODE_M | ISL29023_CMD_I_INT_PERSIST_M |
               ISL29023_CMD_I_INT_FLAG_M);
    ISL29023ReadModifyWrite(&g_sISL29023Inst, ISL29023_O_CMD_I, ~ui8Mask,
                            (ISL29023_CMD_I_OP_MODE_ALS_CONT |
                             ISL29023_CMD_I_INT_PERSIST_8),
                            ISL29023AppCallback, &g_sISL29023Inst);

    //
    // Wait for transaction to complete
    //
    ISL29023AppI2CWait(__FILE__, __LINE__);

    //
    // Configure the upper threshold to 80% of maximum value
    //
    g_sISL29023Inst.pui8Data[1] = 0xCC;
    g_sISL29023Inst.pui8Data[2] = 0xCC;
    ISL29023Write(&g_sISL29023Inst, ISL29023_O_INT_HT_LSB,
                  g_sISL29023Inst.pui8Data, 2, ISL29023AppCallback,
                  &g_sISL29023Inst);

    //
    // Wait for transaction to complete
    //
    ISL29023AppI2CWait(__FILE__, __LINE__);

    //
    // Configure the lower threshold to 20% of maximum value
    //
    g_sISL29023Inst.pui8Data[1] = 0x33;
    g_sISL29023Inst.pui8Data[2] = 0x33;
    ISL29023Write(&g_sISL29023Inst, ISL29023_O_INT_LT_LSB,
                  g_sISL29023Inst.pui8Data, 2, ISL29023AppCallback,
                  &g_sISL29023Inst);
    //
    // Wait for transaction to complete
    //
    ISL29023AppI2CWait(__FILE__, __LINE__);

    //
    //Configure and enable SysTick Timer
    //
    ROM_SysTickPeriodSet(ROM_SysCtlClockGet() / SYSTICKS_PER_SECOND);
    ROM_SysTickIntEnable();
    ROM_SysTickEnable();

    //
    // After all the init and config we start blink the LED
    //
    RGBBlinkRateSet(1.0f);

    //
    // Loop Forever
    //
    while(1)
    {
        ROM_SysCtlSleep();

        if(g_vui8DataFlag)
        {
            g_vui8DataFlag = 0;

            //
            // Get a local floating point copy of the latest light data
            //
            ISL29023DataLightVisibleGetFloat(&g_sISL29023Inst, &fAmbient);

            //
            // Perform the conversion from float to a printable set of integers
            //
            i32IntegerPart = (int32_t)fAmbient;
            i32FractionPart = (int32_t)(fAmbient * 1000.0f);
            i32FractionPart = i32FractionPart - (i32IntegerPart * 1000);
            if(i32FractionPart < 0)
            {
                i32FractionPart *= -1;
            }

            //
            // Print the temperature as integer and fraction parts.
            //
            UARTprintf("Visible Lux: %3d.%03d\n", i32IntegerPart,
                       i32FractionPart);

            //
            // Check if the intensity of light has crossed a threshold. If so
            // then adjust range of sensor readings to track intensity.
            //
            if(g_vui8IntensityFlag)
            {
                //
                // Disable the low priority interrupts leaving only the I2C
                // interrupt enabled.
                //
                ROM_IntPriorityMaskSet(0x40);

                //
                // Reset the intensity trigger flag.
                //
                g_vui8IntensityFlag = 0;

                //
                // Adjust the lux range.
                //
                ISL29023AppAdjustRange(&g_sISL29023Inst);

                //
                // Now we must manually clear the flag in the ISL29023
                // register.
                //
                ISL29023Read(&g_sISL29023Inst, ISL29023_O_CMD_I,
                             g_sISL29023Inst.pui8Data, 1, ISL29023AppCallback,
                             &g_sISL29023Inst);

                //
                // Wait for transaction to complete
                //
                ISL29023AppI2CWait(__FILE__, __LINE__);

                //
                // Disable priority masking so all interrupts are enabled.
                //
                ROM_IntPriorityMaskSet(0);
            }
        }
    }
}