/*****************************************************************************
 Function    : LOS_EvbLedInit
 Description : Init LED device
 Input       : None
 Output      : None
 Return      : None
 *****************************************************************************/
void LOS_EvbLedInit(void)
{
#ifdef LOS_ADuCM450LF
    /* set GPIO output LED 3, 4 and 5 */
    if(ADI_GPIO_SUCCESS != adi_gpio_OutputEnable(ADI_GPIO_PORT0, ADI_GPIO_PIN_13, true))
    {
        dprintf("adi_gpio_SetDirection failed\n");
    }
    if(ADI_GPIO_SUCCESS != adi_gpio_OutputEnable(ADI_GPIO_PORT1, (ADI_GPIO_PIN_12 | ADI_GPIO_PIN_13), true))
    {
        dprintf("adi_gpio_SetDirection failed\n");
    }

    /* set GPIO output LED 3, 4 and 5 off*/
    if(ADI_GPIO_SUCCESS != adi_gpio_SetHigh(ADI_GPIO_PORT0, ADI_GPIO_PIN_13))/*led3 off */
    {
        dprintf("adi_gpio_SetLevel failed\n");
    }
    if(ADI_GPIO_SUCCESS != adi_gpio_SetHigh(ADI_GPIO_PORT1, (ADI_GPIO_PIN_12 | ADI_GPIO_PIN_13)))/*led3 off */
    {
        dprintf("adi_gpio_SetLevel failed\n");
    }
 #endif
    
    return;
}
/*****************************************************************************
 Function    : LOS_EvbLedControl
 Description : Led control function
 Input       : (1) index Led's index
               (2) cmd   Led on or off
 Output      : None
 Return      : None
 *****************************************************************************/
void LOS_EvbLedControl(int index, int cmd)
{
#ifdef LOS_ADuCM450LF
    switch (index)
    {
        case LOS_LED1:
        {
            if (cmd == LED_ON)
            {
                (VOID)adi_gpio_SetLow(ADI_GPIO_PORT0, ADI_GPIO_PIN_13); /*LED3 on */
            }
            else
            {
                (VOID)adi_gpio_SetHigh(ADI_GPIO_PORT0, ADI_GPIO_PIN_13); /*LED3 off */
            }
            break;
        }
        case LOS_LED2:
        {
            if (cmd == LED_ON)
            {
                (VOID)adi_gpio_SetLow(ADI_GPIO_PORT1, ADI_GPIO_PIN_12); /*LED4 on */
            }
            else
            {
                (VOID)adi_gpio_SetHigh(ADI_GPIO_PORT1, ADI_GPIO_PIN_12); /*LED4 off */
            }
            break;
        }
        case LOS_LED3:
        {
            if (cmd == LED_ON)
            {
                (VOID)adi_gpio_SetLow(ADI_GPIO_PORT1, ADI_GPIO_PIN_13); /*LED5 on */
            }
            else
            {
                (VOID)adi_gpio_SetHigh(ADI_GPIO_PORT1, ADI_GPIO_PIN_13); /*LED5 off */
            }
            break;
        }
        default:
        {
            break;
        }
    }
#endif
    
    return;
}
/* Callback from the ADC device */
static void ADCCallback(void *pCBParam, uint32_t Event, void *pArg)
{
    switch (Event)
    {
    case ADI_ADC_EVENT_BUFFER_PROCESSED:
             adi_gpio_SetHigh(LED4);
             adi_gpio_SetLow(DBG_ADC_PIN);
               
             DEBUG_MESSAGE("%d,%d\n",cnt_samples,ADC_DataBuffer[0]);        
             cnt_samples++;
        break;

    default:
        break;
    }
}
void ADC_Setup(void)
{
    ADI_ADC_RESULT  adcResult = ADI_ADC_SUCCESS;
    ADI_ADC_BUFFER Buffer;
    bool_t bCalibrationDone = false;	
    
    /* Open the ADC device */
    adcResult = adi_adc_Open(ADC_DEV_NUM, DeviceMemory, sizeof(DeviceMemory), &hDevice);
    DEBUG_RESULT("Failed to open ADC device",adcResult, ADI_ADC_SUCCESS);

//#ifdef ADC_ENABLE_CALLBACK
    /* Register Callback */
    adcResult = adi_adc_RegisterCallback (hDevice, ADCCallback, NULL);
//#endif

    /* Power up ADC */
    adcResult = adi_adc_PowerUp (hDevice, true);
    DEBUG_RESULT("Failed to power up ADC", adcResult, ADI_ADC_SUCCESS);

    /* Set ADC reference */
    adcResult = adi_adc_SetVrefSource (hDevice, ADI_ADC_VREF_SRC_INT_2_50_V);
    //adcResult = adi_adc_SetVrefSource (hDevice, ADI_ADC_VREF_SRC_EXT);   
    DEBUG_RESULT("Failed to set ADC reference", adcResult, ADI_ADC_SUCCESS);

    /* Enable ADC sub system */
    adcResult = adi_adc_EnableADCSubSystem (hDevice, true);
    DEBUG_RESULT("Failed to enable ADC sub system", adcResult, ADI_ADC_SUCCESS);

    /* Wait for 5.0ms */
    usleep (5000);
    
    /* Start calibration */
    adcResult = adi_adc_StartCalibration (hDevice);
    DEBUG_RESULT("Failed to start calibration", adcResult, ADI_ADC_SUCCESS);

    /* Wait until calibration is done */
    while (!bCalibrationDone)
    {
        adcResult = adi_adc_IsCalibrationDone (hDevice, &bCalibrationDone);
        DEBUG_RESULT("Failed to get the calibration status", adcResult, ADI_ADC_SUCCESS);
    }	
    
    /* Set the delay time */
    adcResult = adi_adc_SetDelayTime ( hDevice, 0);
    DEBUG_RESULT("Failed to set the Delay time ", adcResult, ADI_ADC_SUCCESS);

    /* Set the acquisition time. (Application need to change it based on the impedence) */
    adcResult = adi_adc_SetAcquisitionTime ( hDevice, 10);
    DEBUG_RESULT("Failed to set the acquisition time ", adcResult, ADI_ADC_SUCCESS);	

    /* Populate the buffer structure */
    Buffer.nBuffSize = sizeof(ADC_DataBuffer);
    Buffer.nChannels = ADI_ADC_CHANNEL_0;
    Buffer.nNumConversionPasses = ADC_NUM_SAMPLES;
    Buffer.pDataBuffer = ADC_DataBuffer;
    
        adcResult = adi_adc_Enable (hDevice, true);
    /* Submit the buffer to the driver */
    
    adi_gpio_SetHigh(DBG_ADC_PIN);
    adcResult = adi_adc_SubmitBuffer (hDevice, &Buffer);
    DEBUG_RESULT("Failed to submit buffer ", adcResult, ADI_ADC_SUCCESS);
    


    
}
/*GPT1 timer callback contains the sensor st8-mc*/
static void GPTimer1Callback(void *pCBParam, uint32_t Event, void *pArg)
{
    ADI_ADC_RESULT  adcResult = ADI_ADC_SUCCESS;
    ADI_ADC_BUFFER Buffer;
    adi_tmr_Enable(hDevice1,false); 
  switch(Event)
  {
      case ADI_TMR_EVENT_TIMEOUT:
        switch (curr_state) {
        
	
	/* st8 0 : CO sensor - heater ON for 980 ms*/	
        case 0 : 
          
            if (cnt_samples >= CNT_SAMPLES_AVG) 
             {
               curr_state = 10;//go to PM2.5 sensor - begin by turning on the fan [st8 10]
               cnt_samples = 0;
               adi_gpio_SetHigh(LED3);
               adi_gpio_SetHigh(LED4);
               
	       adi_gpio_SetLow(CO_HEATER);
               adi_gpio_SetLow(CO_SENSE);

               adi_gpio_SetHigh(PM25_FAN);
               adi_tmr_SetLoadValue( hDevice1, GPT1_LOAD_500MSEC);
               adi_tmr_Enable(hDevice1,true); 
               
             }
            else
            {
              adi_gpio_SetHigh(CO_HEATER);
              
	      adi_gpio_SetLow(LED3);
              adi_gpio_Toggle(DBG_ST8_PIN);

              /*Wait until 2 heater-cycles of 490 ms are done - i.e., wait for heater to be ON for 980 ms as per sensor spec.
	        (limitation of GPT1 clock frequency - cannot count 980 ms in one go)*/
	      if (cnt_co_heater_cycles == 1)
              {
                curr_state = 1;  		  
	      }
	      else
	      {            
                curr_state = 0;
	      }
              cnt_co_heater_cycles++;
              adi_tmr_SetLoadValue( hDevice1, GPT1_LOAD_490MSEC);
              adi_tmr_Enable(hDevice1,true); 
           }   
           break;
         
       /* st8 1 : CO sensor - sense circuit ON for 2.5 ms*/	
       case 1 :
               adi_gpio_SetHigh(CO_SENSE);
               adi_gpio_Toggle(DBG_ST8_PIN);
               
               curr_state = 2;
               adi_tmr_SetLoadValue( hDevice1, GPT1_LOAD_2p5MSEC);    
               adi_tmr_Enable(hDevice1,true); 
              
         break;
         
       /* st8 2 : CO sensor - trigger ADC sampling on channel-2 */	
       case 2 :
         
                     /* Populate the buffer structure */
             Buffer.nBuffSize = sizeof(ADC_DataBuffer);
             Buffer.nChannels = ADI_ADC_CHANNEL_3;                                           
             Buffer.nNumConversionPasses = ADC_NUM_SAMPLES;
             Buffer.pDataBuffer = ADC_DataBuffer;
    
             /* Submit the buffer to the driver */
             adcResult = adi_adc_SubmitBuffer (hDevice, &Buffer);
             adi_gpio_Toggle(DBG_ST8_PIN);
             adi_gpio_SetHigh(DBG_ADC_PIN);
             adi_gpio_SetLow(LED4);
                          
             curr_state = 3;
             adi_tmr_SetLoadValue( hDevice1, GPT1_LOAD_2p5MSEC);
             adi_tmr_Enable(hDevice1,true);                         
            
         break;         
       
       /* st8 2 : CO sensor - heater and sense circuit OFF - wait for 14ms before taking next CO measurement */	
        case 3 :
             adi_gpio_SetLow(CO_HEATER);
             adi_gpio_SetLow(CO_SENSE);
             
             adi_gpio_SetHigh(LED3);
             adi_gpio_Toggle(DBG_ST8_PIN);
             
             cnt_co_heater_cycles = 0;
             curr_state = 0;
             adi_tmr_SetLoadValue( hDevice1, GPT1_LOAD_14MSEC);
             adi_tmr_Enable(hDevice1,true); 
                      
         break; 

	/*st8 10: PM2.5 sensor FAN ON */	
        case 10 :
          /*Wait until 4 cycles of 500 ms are done - i.e., wait for fan to be ON for 2s [actually needs to be on for 10s as per sensor spec,
	   * but trying to save power by reducing fan ON time]*/
          if (cnt_fan_cycles == (NUM_FAN_500MS_CYCLES - 1))
          {
            curr_state = 4;  		  
	  }
	  else
	  {            
            curr_state = 10;
	  }
          cnt_fan_cycles++;
          adi_tmr_SetLoadValue( hDevice1, GPT1_LOAD_500MSEC);
          adi_tmr_Enable(hDevice1,true); 
          break;

	/*st8 4: PM2.5 sensor LED ON for 0.28ms */	
       case 4 : 
          
            if (cnt_samples >= CNT_SAMPLES_AVG) 
             {
               adi_tmr_Enable(hDevice1, false);
               adi_gpio_SetHigh(LED3);
               adi_gpio_SetHigh(LED4);
               adi_gpio_SetLow(PM25_LED);
               adi_gpio_SetLow(PM25_FAN);
               //cnt_samples = 0;                                                              //change
             }
            else
            {
              adi_gpio_SetHigh(PM25_LED);
              
	      adi_gpio_SetLow(LED3);
              adi_gpio_Toggle(DBG_ST8_PIN);

              curr_state      = 5;
              adi_tmr_SetLoadValue( hDevice1, GPT1_LOAD_0p28MSEC);
              adi_tmr_Enable(hDevice1,true); 
           }   
           break;         
	
	/*st8 5: PM2.5 sensor - trigger ADC sampling on channel-3 */	
        case 5 :
             adi_gpio_SetLow(LED4);
             /* Populate the buffer structure */
             Buffer.nBuffSize = sizeof(ADC_DataBuffer);
             Buffer.nChannels = ADI_ADC_CHANNEL_2;                                             
             Buffer.nNumConversionPasses = ADC_NUM_SAMPLES;
             Buffer.pDataBuffer = ADC_DataBuffer;
    
             /* Submit the buffer to the driver */
             adcResult = adi_adc_SubmitBuffer (hDevice, &Buffer);
             adi_gpio_Toggle(DBG_ST8_PIN);
             adi_gpio_SetHigh(DBG_ADC_PIN);
             
	     curr_state = 6;  
             adi_tmr_SetLoadValue( hDevice1, GPT1_LOAD_0p04MSEC); 
             adi_tmr_Enable(hDevice1,true); 
             
         break;   

	/*st8 6: PM2.5 sensor - LED OFF, wait for 9.68 ms before next PM2.5 measurement */	
        case 6 :
             adi_gpio_SetLow(PM25_LED);
             
             adi_gpio_SetHigh(LED3);
             adi_gpio_Toggle(DBG_ST8_PIN);

             curr_state = 4;  
             adi_tmr_SetLoadValue( hDevice1, GPT1_LOAD_9p68MSEC);
             //adi_tmr_SetLoadValue( hDevice1, GPT1_LOAD_50MSEC);
             adi_tmr_Enable(hDevice1,true);                       

         break;         
         
       default :
         break;
     }
  
        break;
      case ADI_TMR_EVENT_CAPTURED:
        break;
      default:
        break;
  }
  
}
int main(void)
{
     
    /* Clock initialization */
    SystemInit();

    /* test system initialization */
    test_Init();
        //adi_gpio_OutputEnable(EN_5V, true);
        //adi_gpio_SetHigh(EN_5V);
    
  /*    SWITCHED TO LOW POWER MODE - ACTIVE MODE    */
  pwrResult = adi_pwr_EnterLowPowerMode(ADI_PWR_MODE_ACTIVE,NULL,0x00);  //Low Power Active mode
  DEBUG_RESULT("\n Failed to enter active mode %04d",pwrResult,ADI_PWR_SUCCESS);
  /*    BUCK CONVERTER ENABLED TO REDUCE POWER      */
  adi_pwr_EnableHPBuck(true); 
  
  NUM_FAN_500MS_CYCLES = fanOnTime/0.5;//Number of 500ms cycles equals ratio of given fanOnTime to 0.5 
  
    do 
    {
      if(ADI_PWR_SUCCESS != adi_pwr_Init())
        {
          DEBUG_MESSAGE("Failed to intialize the power service\n");
          break;
        }
      
      if(ADI_PWR_SUCCESS != adi_pwr_SetLFClockMux(ADI_CLOCK_MUX_LFCLK_LFXTAL))
      {
        return(eResult);
      }
      
      if(ADI_PWR_SUCCESS != adi_pwr_EnableClockSource(ADI_CLOCK_SOURCE_HFXTAL, true))
      {
        return(eResult);
      }

      if(ADI_PWR_SUCCESS != adi_pwr_SetRootClockMux(ADI_CLOCK_MUX_ROOT_HFXTAL))
      {
        return(eResult);
      }

      
      if(ADI_PWR_SUCCESS != adi_pwr_EnableClockSource(ADI_CLOCK_SOURCE_LFXTAL,true))
      {
        return(eResult);
      }
   
      if (ADI_PWR_SUCCESS != adi_pwr_SetClockDivider(ADI_CLOCK_HCLK,1))
      {
          DEBUG_MESSAGE("Failed to intialize the power service\n");
      }
      if (ADI_PWR_SUCCESS != adi_pwr_SetClockDivider(ADI_CLOCK_PCLK,1))
      {
          DEBUG_MESSAGE("Failed to intialize the power service\n");
      }

  
      if(ADI_RTC_SUCCESS !=rtc_Init())
        {
          DEBUG_MESSAGE("\nFailed to initialize RTC device \n");
        }
      

      
      if(ADI_GPIO_SUCCESS != adi_gpio_Init(gpioMemory, ADI_GPIO_MEMORY_SIZE))
        {
            DEBUG_MESSAGE("adi_gpio_Init failed\n");
            break;
        }
      //P0.13 --> LED3
      adi_gpio_OutputEnable(LED3, true);
      //P1.12 --> LED4 
      adi_gpio_OutputEnable(LED4, true);
      adi_gpio_OutputEnable(CO_HEATER, true);
      adi_gpio_OutputEnable(CO_SENSE, true);
      adi_gpio_OutputEnable(PM25_LED, true);
      adi_gpio_OutputEnable(PM25_FAN, true);
      adi_gpio_OutputEnable(DBG_ST8_PIN, true);
      adi_gpio_OutputEnable(DBG_ADC_PIN, true);

      adi_gpio_SetLow(CO_HEATER);
      adi_gpio_SetLow(CO_SENSE);
      adi_gpio_SetLow(PM25_LED);
      adi_gpio_SetLow(PM25_FAN);
      adi_gpio_SetLow(DBG_ADC_PIN);   
      adi_gpio_SetHigh(LED3);
      adi_gpio_SetHigh(LED4);
      
      ADC_Setup();
      
      adi_tmr_Open(TIMER_DEVICE_1,aDeviceMemory1,ADI_TMR_MEMORY_SIZE,&hDevice1); 
      adi_tmr_RegisterCallback( hDevice1, GPTimer1Callback ,hDevice1);
      
      adi_tmr_SetPrescaler(hDevice1, ADI_GPT_PRESCALER_256);
      adi_tmr_SetLoadValue( hDevice1, GPT1_LOAD_1SEC);
     
      DEBUG_MESSAGE("AQ Sensor initializing!\n");    
        
    }while(0);
    
    do
    {}
    while(1);
    
    
 
}
int main(void)
{
     
    /* Clock initialization */
    SystemInit();

    /* test system initialization */
    test_Init();
        //adi_gpio_OutputEnable(EN_5V, true);
        //adi_gpio_SetHigh(EN_5V);
        
    do 
    {
      if(ADI_PWR_SUCCESS != adi_pwr_Init())
        {
          DEBUG_MESSAGE("Failed to intialize the power service\n");
          break;
        }
      
      if(ADI_PWR_SUCCESS != adi_pwr_SetLFClockMux(ADI_CLOCK_MUX_LFCLK_LFXTAL))
      {
        return(eResult);
      }
      
      if(ADI_PWR_SUCCESS != adi_pwr_EnableClockSource(ADI_CLOCK_SOURCE_HFXTAL, true))
      {
        return(eResult);
      }

      if(ADI_PWR_SUCCESS != adi_pwr_SetRootClockMux(ADI_CLOCK_MUX_ROOT_HFXTAL))
      {
        return(eResult);
      }

      
      if(ADI_PWR_SUCCESS != adi_pwr_EnableClockSource(ADI_CLOCK_SOURCE_LFXTAL,true))
      {
        return(eResult);
      }
   
      if (ADI_PWR_SUCCESS != adi_pwr_SetClockDivider(ADI_CLOCK_HCLK,1))
      {
          DEBUG_MESSAGE("Failed to intialize the power service\n");
      }
      if (ADI_PWR_SUCCESS != adi_pwr_SetClockDivider(ADI_CLOCK_PCLK,1))
      {
          DEBUG_MESSAGE("Failed to intialize the power service\n");
      }

  
      if(ADI_RTC_SUCCESS !=rtc_Init())
        {
          DEBUG_MESSAGE("\nFailed to initialize RTC device \n");
        }
      

      
      if(ADI_GPIO_SUCCESS != adi_gpio_Init(gpioMemory, ADI_GPIO_MEMORY_SIZE))
        {
            DEBUG_MESSAGE("adi_gpio_Init failed\n");
            break;
        }
      //P0.13 --> LED3
      adi_gpio_OutputEnable(LED3, true);
      //P1.12 --> LED4 
      adi_gpio_OutputEnable(LED4, true);
      adi_gpio_OutputEnable(CO_HEATER, true);
      adi_gpio_OutputEnable(CO_SENSE, true);
      adi_gpio_OutputEnable(PM25_LED, true);
      adi_gpio_OutputEnable(PM25_FAN, true);
      adi_gpio_OutputEnable(DBG_ST8_PIN, true);
      adi_gpio_OutputEnable(DBG_ADC_PIN, true);

      adi_gpio_SetLow(CO_HEATER);
      adi_gpio_SetLow(CO_SENSE);
      adi_gpio_SetLow(PM25_LED);
      adi_gpio_SetLow(PM25_FAN);
      adi_gpio_SetLow(DBG_ADC_PIN);   
      adi_gpio_SetHigh(LED3);
      adi_gpio_SetHigh(LED4);
      
      ADC_Setup();
      
      adi_tmr_Open(TIMER_DEVICE_1,aDeviceMemory1,ADI_TMR_MEMORY_SIZE,&hDevice1); 
      adi_tmr_RegisterCallback( hDevice1, GPTimer1Callback ,hDevice1);
      
      adi_tmr_SetPrescaler(hDevice1, ADI_GPT_PRESCALER_256);
      adi_tmr_SetLoadValue( hDevice1, GPT1_LOAD_1SEC);
     
      DEBUG_MESSAGE("AQ Sensor initializing!\n");    
        
    }while(0);
    
    do
    {}
    while(1);
    
    
 
}