/**
*
* This function runs a test on the System Monitor/ADC device using the
* driver APIs.
*
* The function does the following tasks:
*	- Initiate the System Monitor/ADC device driver instance
*	- Run self-test on the device
*	- Reset the device
*	- Set up alarm for VCCINT
*	- Set up the configuration registers for single channel continuous mode
*	for VCCINT channel
*	- Setup interrupt system
*	- Enable interrupts
*	- Wait until the VCCINT alarm interrupt occurs
*
* @param	IntcInstancePtr is a pointer to the Interrupt Controller
*		driver Instance.
* @param	SysMonInstPtr is a pointer to the XSysMon driver Instance.
* @param	SysMonDeviceId is the XPAR_<SYSMON_ADC_instance>_DEVICE_ID value
*		from xparameters.h.
* @param	SysMonIntrId is
*		XPAR_<INTC_instance>_<SYSMON_ADC_instance>_VEC_ID
*		value from xparameters.h
*
* @return
*		- XST_SUCCESS if the example has completed successfully.
*		- XST_FAILURE if the example has failed.
*
* @note		This function may never return if no interrupt occurs.
*
****************************************************************************/
int SysMonSingleChannelIntrExample(XIntc* IntcInstancePtr,
					XSysMon* SysMonInstPtr,
					u16 SysMonDeviceId,
					u16 SysMonIntrId)
{
	int Status;
	XSysMon_Config *ConfigPtr;
	u16 VccintData;
	u32 IntrStatus;

	/*
	 * Initialize the SysMon driver.
	 */
	ConfigPtr = XSysMon_LookupConfig(SysMonDeviceId);
	if (ConfigPtr == NULL) {
		return XST_FAILURE;
	}
	XSysMon_CfgInitialize(SysMonInstPtr, ConfigPtr, ConfigPtr->BaseAddress);

	/*
	 * Self Test the System Monitor/ADC device.
	 */
	Status = XSysMon_SelfTest(SysMonInstPtr);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Set the ADCCLK frequency equal to 1/32 of System clock for the System
	 * Monitor/ADC in the Configuration Register 2.
	 */
	XSysMon_SetAdcClkDivisor(SysMonInstPtr, 32);

	/*
	 * Set the sequencer in Single channel mode.
	 */
	XSysMon_SetSequencerMode(SysMonInstPtr, XSM_SEQ_MODE_SINGCHAN);

	/*
	 * Set the configuration registers for single channel continuous mode
	 * of operation for the VCCINT channel.
	 */
	Status=  XSysMon_SetSingleChParams(SysMonInstPtr, XSM_CH_VCCINT,
						FALSE, FALSE, FALSE);
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}


	/*
	 * Disable all the alarms in the Configuration Register 1.
	 */
	XSysMon_SetAlarmEnables(SysMonInstPtr, 0x0);

	/*
	 * Set up Alarm threshold registers for the VCCINT
	 * High limit and lower limit so that the alarm does not occur.
	 */
	XSysMon_SetAlarmThreshold(SysMonInstPtr, XSM_ATR_VCCINT_UPPER, 0xFFFF);
	XSysMon_SetAlarmThreshold(SysMonInstPtr, XSM_ATR_VCCINT_LOWER, 0x0);


	/*
	 * Setup the interrupt system.
	 */
	Status = SysMonSetupInterruptSystem(IntcInstancePtr,
					    SysMonInstPtr,
					    SysMonIntrId);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}


	/*
	 * Clear any bits set in the Interrupt Status Register.
	 */
	IntrStatus = XSysMon_IntrGetStatus(SysMonInstPtr);
	XSysMon_IntrClear(SysMonInstPtr, IntrStatus);


	/*
	 * Enable EOC interrupt and Alarm 1 interrupt for on-chip VCCINT.
	 */
	XSysMon_IntrEnable(SysMonInstPtr, XSM_IPIXR_EOC_MASK |
						XSM_IPIXR_VCCINT_MASK);

	/*
	 * Enable global interrupt of System Monitor.
	 */
	XSysMon_IntrGlobalEnable(SysMonInstPtr);


	/*
	 * Wait till the End of Conversion occurs.
	 */
	EocFlag = FALSE; 		/* Clear the EOC Flag */
	while (EocFlag != TRUE);


	/*
	 * Read the ADC converted Data from the data registers for VCCINT.
	 */
	VccintData = XSysMon_GetAdcData(SysMonInstPtr, XSM_CH_VCCINT);


	/*
	 * Set up Alarm threshold registers for the VCCINT
	 * High limit and lower limit so that the alarm occurs.
	 */
	XSysMon_SetAlarmThreshold(SysMonInstPtr, XSM_ATR_VCCINT_UPPER,
						VccintData - 0x007F);
	XSysMon_SetAlarmThreshold(SysMonInstPtr, XSM_ATR_VCCINT_LOWER,
						VccintData - 0x007F);


	VccintIntr = FALSE;	/* Clear the flag */


	/*
	 * Enable Alarm 1 for VCCINT
	 */
	XSysMon_SetAlarmEnables(SysMonInstPtr, XSM_CFR1_ALM_VCCINT_MASK);

	/*
	 * Wait until an Alarm 1 interrupt occurs.
	 */
	while (1) {

		if (VccintIntr == TRUE) {
			/*
			 * Alarm 1 - VCCINT alarm interrupt has occurred.
			 * The required processing should be put here.
			 */
			break;
		}
	}

	/*
	 * Disable global interrupt of System Monitor.
	 */
	XSysMon_IntrGlobalDisable(SysMonInstPtr);

	return XST_SUCCESS;
}
/***************************************************************************
 * Looks up the current config and initializes XADC_WIZ
 *
 * @ Channel: Chooses channel for single channel mode. Options are Channel 6, Channel 7,
 * 			Channel 14 and Channel 15.
 *
 * @ SequencerMode: Choose between SINGLE_CHANNEL_MODE (= XSM_SEQ_MODE_SINGCHAN) for single channel mode
 * 				  or CONTINUOUS_SAMPLING_MODE(= XSM_SEQ_MODE_CONTINPASS) for continuous sequencing mode.
 *
 * Always in Differential mode
 * Always in continuous mode
 * Always slow AcQCycles ( for sequence mode of operations adjust XSysMon_SetSeqAcqTime(&SysMon , SEQ_CHANNELS) to
 * 							XSysMon_SetSeqAcqTime(&SysMon , ~SEQ_CHANNELS) )
 *
 ***************************************************************************/
void init_XADC_WIZ(char channel, u8 SequencerMode)
{
    int Status;
    int ParameterStatus;
    int SequenceStatus;
    int InputStatus;
    int AcqStatus;

    int IncreaseAcqCycles = FALSE;
    int IsEventMode = FALSE;
    int IsDifferentialMode = TRUE;
    u8 Divisor = 0;


    XSysMon_Config *Config;

    Config = XSysMon_LookupConfig(XPAR_XADC_WIZ_0_DEVICE_ID);
    if (NULL == Config) {
        //return XST_FAILURE;
    }
    Status = XSysMon_CfgInitialize(&SysMon,Config ,Config->BaseAddress);
    if (Status != XST_SUCCESS) {
        xil_printf("XADC_WIZ initialization FAILED!\n \r");
        //return XST_FAILURE;
    }
    else {
        xil_printf("XADC_WIZ initialization SUCCESS!\n \r");
    }

    /* NO averaging*/

    XSysMon_SetAvg(&SysMon, XSM_AVG_0_SAMPLES);


    /* Calibrate ADC gain and offset + Power Supply gain and offset*/

    XSysMon_SetCalibEnables(&SysMon, XSM_CFR1_CAL_ADC_GAIN_OFFSET_MASK | XSM_CFR1_CAL_PS_GAIN_OFFSET_MASK);

    /* Sets the channel seqence mode:
     * - Default safe mode (XSM_SEQ_MODE_SAFE)
     *	- One pass through sequence (XSM_SEQ_MODE_ONEPASS)
     *	- Continuous channel sequencing (XSM_SEQ_MODE_CONTINPASS)
     *	- Single Channel/Sequencer off (XSM_SEQ_MODE_SINGCHAN)
     *	- Simulataneous sampling mode (XSM_SEQ_MODE_SIMUL)
     *	- Independent mode (XSM_SEQ_MODE_INDEPENDENT)
     *
     *	NOTE: We will only use single channel mode and continious channel sequencing mode!!!
     */

    if(SequencerMode = XSM_SEQ_MODE_SINGCHAN)
    {

        XSysMon_SetSequencerMode(&SysMon,XSM_SEQ_MODE_SINGCHAN);

        /*  Sets the parameters for the single channel mode
         *  int ParameterStatus;			 => Return value, =1 when failed
         *  int IncreaseAcqCycles = FALSE;   => TRUE: increased to 10 ADCCLK cycles | FALSE: default 4 ADCCLK cycles
         *  int IsEventMode = FALSE;		 => TRUE: event driven sampling mode    | FALSE: continious sampling mode
         *  int IsDifferentialMode = TRUE;   => TRUE: differential mode             | FALSE: unipolar mode
         */
        ParameterStatus = XSysMon_SetSingleChParams(&SysMon,(XSM_CH_AUX_MIN + (channel -1)),
                          IncreaseAcqCycles, IsEventMode, IsDifferentialMode);
        if (ParameterStatus != XST_SUCCESS) {
            xil_printf("Setting SingleChannelParameters FAILED!\n \r");
        }
    }
    else if(SequencerMode = XSM_SEQ_MODE_CONTINPASS)
    {
        XSysMon_SetSequencerMode(&SysMon,XSM_SEQ_MODE_SAFE);  /* Settings need to be applied in safe mode*/

        XSysMon_SetSequencerEvent(&SysMon, IsEventMode);      /* IsEventmode = FALSE => continious sampling!*/

        XSysMon_SetAdcClkDivisor(&SysMon, Divisor);		   /* Divisor sets the clockdevision for the ADC sampling*/

        SequenceStatus=  XSysMon_SetSeqChEnables(&SysMon,SEQ_CHANNELS);		   /* Selects channels to sequence*/

        if (SequenceStatus != XST_SUCCESS) {
            xil_printf("Enabling Sequence Channels FAILED!\n \r");
        }
        InputStatus =  XSysMon_SetSeqInputMode(&SysMon, SEQ_CHANNELS);	   /* Sets the channels to differential mode */

        if (InputStatus != XST_SUCCESS) {
            xil_printf("Setting Input Mode FAILED!\n \r");
        }

        AcqStatus =  XSysMon_SetSeqAcqTime(&SysMon , SEQ_CHANNELS);	   /* If function is enabled: Acquisition cycles will be extended to 10 ADCCLK cycles*/

        if (AcqStatus != XST_SUCCESS) {
            xil_printf("Setting AcqTime FAILED!\n \r");
        }
        XSysMon_SetSequencerMode(&SysMon,XSM_SEQ_MODE_CONTINPASS);		   /* Continuous sampling mode enabled */
    }
}