/**
*   @copyright       © 2026 Microchip Technology Inc.
    Microchip Technology Inc. and its subsidiaries. You may use this
    software and any derivatives exclusively with Microchip products.

    THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
    EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
    WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
    PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION
    WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.

    IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
    INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
    WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS
    BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE
    FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN
    ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
    THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.

    MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE
    TERMS. 
*
*************************************************************************/

/*************************************************************************
 *  @file           diag_adc.h
 *  @version       	1.0
 *  @brief     		This file has the declarations for the ADC diagnostic 
 *					functions.
 *************************************************************************/

/**
 * @defgroup functions Functions
 * @defgroup macros Macros
 * @defgroup errorcodes ErrorCodes
 * @defgroup enums Enums
*/
 
#ifndef DIAG_ADC_H
#define DIAG_ADC_H

/*Section: Included Files*/
#include <xc.h>
#include "diag.h"

/** Macros*/
/**
 @ingroup macros
 @def DIAG_ADC_LIN_INPUT_START_RANGE
 The initial input range for ADC linearity diagnostics as determined by the DAC's range 
 available within the device.
 */
#define DIAG_ADC_LIN_INPUT_START_RANGE 0x00D0U

/**
 @ingroup macros
 @def DIAG_ADC_LIN_INPUT_END_RANGE
 The end input range for ADC linearity diagnostics as determined by the DAC's range
 available within the device.
 */
#define DIAG_ADC_LIN_INPUT_END_RANGE 0x0F30U

/* Enumerations */
/**
 @ingroup enums
 @enum DIAG_ADC_CHANNELS
 Defines the ADC Channels available.
 @var  DIAG_ADC_CHANNELS::DIAG_ADC1_CH0
 @var  DIAG_ADC_CHANNELS::DIAG_ADC1_CH1
 @var  DIAG_ADC_CHANNELS::DIAG_ADC1_CH2
 @var  DIAG_ADC_CHANNELS::DIAG_ADC1_CH3
 @var  DIAG_ADC_CHANNELS::DIAG_ADC1_CH4
 @var  DIAG_ADC_CHANNELS::DIAG_ADC1_CH5
 @var  DIAG_ADC_CHANNELS::DIAG_ADC1_CH6
 @var  DIAG_ADC_CHANNELS::DIAG_ADC1_CH7
 @var  DIAG_ADC_CHANNELS::DIAG_ADC2_CH0
 @var  DIAG_ADC_CHANNELS::DIAG_ADC2_CH1
 @var  DIAG_ADC_CHANNELS::DIAG_ADC2_CH2
 @var  DIAG_ADC_CHANNELS::DIAG_ADC2_CH3
 @var  DIAG_ADC_CHANNELS::DIAG_ADC2_CH4
 @var  DIAG_ADC_CHANNELS::DIAG_ADC2_CH5
 @var  DIAG_ADC_CHANNELS::DIAG_ADC2_CH6
 @var  DIAG_ADC_CHANNELS::DIAG_ADC2_CH7
 @var  DIAG_ADC_CHANNELS::DIAG_ADC3_CH0
 @var  DIAG_ADC_CHANNELS::DIAG_ADC3_CH1
 @var  DIAG_ADC_CHANNELS::DIAG_ADC3_CH2
 @var  DIAG_ADC_CHANNELS::DIAG_ADC3_CH3
 @var  DIAG_ADC_CHANNELS::DIAG_ADC3_CH4
 @var  DIAG_ADC_CHANNELS::DIAG_ADC3_CH5
 @var  DIAG_ADC_CHANNELS::DIAG_ADC3_CH6
 @var  DIAG_ADC_CHANNELS::DIAG_ADC3_CH7
 @var  DIAG_ADC_CHANNELS::DIAG_ADC4_CH0
 @var  DIAG_ADC_CHANNELS::DIAG_ADC4_CH1
 @var  DIAG_ADC_CHANNELS::DIAG_ADC4_CH2
 @var  DIAG_ADC_CHANNELS::DIAG_ADC4_CH3
 @var  DIAG_ADC_CHANNELS::DIAG_ADC4_CH4
 @var  DIAG_ADC_CHANNELS::DIAG_ADC4_CH5
 @var  DIAG_ADC_CHANNELS::DIAG_ADC4_CH6
 @var  DIAG_ADC_CHANNELS::DIAG_ADC4_CH7 
 @var  DIAG_ADC_CHANNELS::DIAG_ADC5_CH0
 @var  DIAG_ADC_CHANNELS::DIAG_ADC5_CH1
 @var  DIAG_ADC_CHANNELS::DIAG_ADC5_CH2
 @var  DIAG_ADC_CHANNELS::DIAG_ADC5_CH3
 @var  DIAG_ADC_CHANNELS::DIAG_ADC5_CH4
 @var  DIAG_ADC_CHANNELS::DIAG_ADC5_CH5
 @var  DIAG_ADC_CHANNELS::DIAG_ADC5_CH6
 @var  DIAG_ADC_CHANNELS::DIAG_ADC5_CH7
 @var  DIAG_ADC_CHANNELS::DIAG_ADC5_CH8
 @var  DIAG_ADC_CHANNELS::DIAG_ADC5_CH9
 @var  DIAG_ADC_CHANNELS::DIAG_ADC5_CH10
 @var  DIAG_ADC_CHANNELS::DIAG_ADC5_CH11
 @var  DIAG_ADC_CHANNELS::DIAG_ADC5_CH12
 @var  DIAG_ADC_CHANNELS::DIAG_ADC5_CH13
 @var  DIAG_ADC_CHANNELS::DIAG_ADC5_CH14
 @var  DIAG_ADC_CHANNELS::DIAG_ADC5_CH15
*/
typedef enum
{
    DIAG_ADC1_CH0  = 0x0000U,
    DIAG_ADC1_CH1  = 0x0001U,
    DIAG_ADC1_CH2  = 0x0002U,
    DIAG_ADC1_CH3  = 0x0003U,
    DIAG_ADC1_CH4  = 0x0004U,
    DIAG_ADC1_CH5  = 0x0005U,
    DIAG_ADC1_CH6  = 0x0006U,
    DIAG_ADC1_CH7  = 0x0007U,
    DIAG_ADC2_CH0  = 0x0100U,
    DIAG_ADC2_CH1  = 0x0101U,
    DIAG_ADC2_CH2  = 0x0102U,
    DIAG_ADC2_CH3  = 0x0103U,
    DIAG_ADC2_CH4  = 0x0104U,
    DIAG_ADC2_CH5  = 0x0105U,
    DIAG_ADC2_CH6  = 0x0106U,
    DIAG_ADC2_CH7  = 0x0107U,
    DIAG_ADC3_CH0  = 0x0200U,
    DIAG_ADC3_CH1  = 0x0201U,
    DIAG_ADC3_CH2  = 0x0202U,
    DIAG_ADC3_CH3  = 0x0203U,
    DIAG_ADC3_CH4  = 0x0204U,
    DIAG_ADC3_CH5  = 0x0205U,
    DIAG_ADC3_CH6  = 0x0206U,
    DIAG_ADC3_CH7  = 0x0207U,
    DIAG_ADC4_CH0  = 0x0300U,
    DIAG_ADC4_CH1  = 0x0301U,
    DIAG_ADC4_CH2  = 0x0302U,
    DIAG_ADC4_CH3  = 0x0303U,
    DIAG_ADC4_CH4  = 0x0304U,
    DIAG_ADC4_CH5  = 0x0305U,
    DIAG_ADC4_CH6  = 0x0306U,
    DIAG_ADC4_CH7  = 0x0307U,
    DIAG_ADC5_CH0  = 0x0400U,
    DIAG_ADC5_CH1  = 0x0401U,
    DIAG_ADC5_CH2  = 0x0402U,
    DIAG_ADC5_CH3  = 0x0403U,
    DIAG_ADC5_CH4  = 0x0404U,
    DIAG_ADC5_CH5  = 0x0405U,
    DIAG_ADC5_CH6  = 0x0406U,
    DIAG_ADC5_CH7  = 0x0407U,
    DIAG_ADC5_CH8  = 0x0408U,
    DIAG_ADC5_CH9  = 0x0409U,
    DIAG_ADC5_CH10  = 0x040AU,
    DIAG_ADC5_CH11  = 0x040BU,
    DIAG_ADC5_CH12  = 0x040CU,
    DIAG_ADC5_CH13  = 0x040DU,
    DIAG_ADC5_CH14  = 0x040EU,
    DIAG_ADC5_CH15  = 0x040FU
}DIAG_ADC_CHANNELS;

/**Structures*/
/**
 @struct DIAG_ADC_LIN_MON_RESULT
 Maintains the linearity monotonicity test results.
 @var  DIAG_ADC_LIN_MON_RESULT::resultLinMon
 Linearity Monotonicity Result.
 @var  DIAG_ADC_LIN_MON_RESULT::lastTestFailCurrentResult
 ADC result for the last failed current iteration.
 @var  DIAG_ADC_LIN_MON_RESULT::lastTestFailPreviousResult
 ADC result for the last failed previous iteration.
 @var  DIAG_ADC_LIN_MON_RESULT::failCount
 Number of failures in the ADC conversions.
 @var  DIAG_ADC_LIN_MON_RESULT::stuckAtHighValue
 Indicates which bit is stuck at high value.
 @var  DIAG_ADC_LIN_MON_RESULT::stuckAtLowValue
 Indicates which bit is stuck at low value.
*/
typedef struct
{
    uint32_t resultLinMon;
    uint16_t lastTestFailCurrentResult;
    uint16_t lastTestFailPreviousResult;
    uint16_t failCount;
    uint16_t stuckAtHighValue;
    uint16_t stuckAtLowValue;
}DIAG_ADC_LIN_MON_RESULT;

/* Function Declarations */

/**
 @ingroup functions
 @brief **Software Requirement Reference ID : SW_ADC_BOUNDARY_MONITOR_TEST_01**\n
 The diagnostic API is aimed at detecting failures in the circuits dedicated to 
 ADC boundary monitoring. On successful detection the diagnostics returns a pass 
 otherwise fail.
 ADC Interrupts for the corresponding channel shall be disabled before 
 calling the diagnostics.
 @param adcChannelNumber - ADC channel number
 @param boundaryValueLow - Lower Boundary Value
 @param boundaryValueHigh - Higher Boundary Value
 @return @ref DIAG_PASS \n
 @return @ref DIAG_FAIL \n
 @return @ref DIAG_INVALID_PARAM \n
 @par
Imageref DIAG_ADC_BoundaryMonitorTest_UML.svg "ADC Boundary Monitor Test"
Imageref DIAG_ADC_BoundaryMonitorTest_ClassDiagram.svg "ADC Boundary Monitor Class Diagram"
 */

uint32_t DIAG_ADC_BoundaryMonitorTest(DIAG_ADC_CHANNELS adcChannelNumber, 
        uint32_t boundaryValueLow, uint32_t boundaryValueHigh);

/**
 @ingroup functions
 @brief **Software Requirement Reference ID : SW_ADC_LINEARITY_MONOTONICITY_TEST_01**\n
 The diagnostic API performs a linearity and monotonicity diagnostic test on an 
 Analog-to-Digital Converter (ADC) channel using a Digital-to-Analog Converter (DAC) 
 to generate input signals. 
 The goal is to verify that the ADC output increases monotonically and linearly 
 as the input voltage is incremented, and to check for any bits stuck at high or low values.
 ADC Interrupts for the corresponding channel shall be disabled before 
 calling the diagnostics.

 Design:

    1. Input Signal Generation
    DAC Usage: A Digital-to-Analog Converter (DAC) is used to generate the input signal for the ADC.
    Ramp Creation: The DAC output is incremented in steady steps, creating a ramp-like analog signal that covers the ADC's input range.

    2. Linearity, Monotonicity, Bit Stuck Checks
    Initializes the DAC with the starting input value.
    Performs an initial ADC conversion and records the result.
    Gradually increases the DAC output in specified increments, conducting ADC conversions at each increment.
    In the present design, DAC output is incremented by 16 units.
    At each increment:
    Determines the difference between the current and previous ADC readings.
    Assesses whether this difference falls within the acceptable range defined by the increment and tolerance thereby
    validating linearity and monotonicity.
    Increases the failure count if the deviation is outside the permissible limit and flags the test as failed.
    Updates variables that monitor for bits stuck at high or low states in the ADC output.
    Sets the previous result to the current value for the next comparison.

    Bit-Stuck Verification:
    After completing all increments, evaluates the tracking variables to identify any bits stuck at high or low levels.
    Flags the test as failed if any stuck bits are detected.

 @param adcChannelNumber - ADC channel number
 @param tolerance - The tolerance in counts, which specifies maximum permissible deviation from the ideal ADC output increment for each test step.
 Typically, the step size can be given as the tolerance but can be changed as per the noise level in the usage environment.
 @return @ref DIAG_PASS \n
 @return @ref DIAG_FAIL \n
 @return @ref DIAG_INVALID_PARAM \n
 @par
Imageref DIAG_ADC_LinearityMonotonicityTest_UML.svg "ADC Linearity Monotonicity Test"
Imageref DIAG_ADC_LinearityMonotonicityTest_ClassDiagram.svg "ADC Linearity Monotonicity Class Diagram"
 */

uint32_t DIAG_ADC_LinearityMonotonicityTest(DIAG_ADC_CHANNELS adcChannelNumber, 
                                        uint8_t tolerance);

/**
 @ingroup functions
 @brief **Software Requirement Reference ID : SW_ADC_STARTUP_TEST_01**\n
 The diagnostic API is aimed at detecting failures in the overall ADC module.
 On successful detection the diagnostics returns a pass otherwise fail.
 ADC Interrupts for the corresponding channel shall be disabled before 
 calling the diagnostics.
 @param adcChannelNumber - ADC channel number
 @return @ref DIAG_PASS \n
 @return @ref DIAG_FAIL \n
 @return @ref DIAG_INVALID_PARAM \n
 @par
Imageref DIAG_ADC_StartupTest_UML.svg "ADC StartupTest"
Imageref DIAG_ADC_StartupTest_ClassDiagram.svg "ADC StartupTest Class Diagram"
 */

uint32_t DIAG_ADC_StartupTest(DIAG_ADC_CHANNELS adcChannelNumber);

/**
 @ingroup functions
 @brief **Software Requirement Reference ID : SW_ADC_LINEARITY_MONOTONICITY_TEST_01**\n
 The diagnostic API returns the result of linearity monotonicity test.
 @param None
 @return @ref DIAG_ADC_LIN_MON_RESULT
 */

DIAG_ADC_LIN_MON_RESULT DIAG_ADC_GetLinearityMonotonicityResult(void);

#endif /* DIAG_ADC_H */
