/**
*   @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_clock.h
 *  @version       	1.0
 *  @brief     		This file has the declarations for the clock monitor
 *                  diagnostic tests.
 *************************************************************************/

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

#include "diag.h"

/**
 * 
 * @ingroup macros
 * @def DIAG_CLOCKMON_FAULT_UNDETECTED
 * @brief Indicates that no fault has been detected by the clock monitor.
 *
 * This macro defines the value returned or set when the clock monitor has not detected
 * any fault condition. Used as a status indicator in diagnostic routines.
 */
#define DIAG_CLOCKMON_FAULT_UNDETECTED 0x55U

/**
 * @ingroup macros
 * @def DIAG_CLOCKMON_FAULT_DETECTED
 * @brief Indicates that a fault has been detected by the clock monitor.
 *
 * This macro defines the value returned or set when the clock monitor has detected
 * a fault condition. Used as a status indicator in diagnostic routines.
 */
#define DIAG_CLOCKMON_FAULT_DETECTED 0xAAU


/**
 * @ingroup enums 
 * @enum DIAG_CLOCK_FLTINJ_TYPE
 * @brief Specifies the type of clock fault to inject during the diagnostic test.
 *
 * This enumeration is used to select the nature of the fault that will be injected
 * into the monitored clock to test the detection capability of the clock monitor.
 */
typedef enum 
{
    DIAG_CLOCK_LOW_FREQ_DRIFT_FLTINJ = 1,   /**< Injects a low frequency drift fault */
    DIAG_CLOCK_HIGH_FREQ_DRIFT_FLTINJ,      /**< Injects a high frequency drift fault */
    DIAG_CLOCK_CATASTROPHIC_FLTINJ          /**< Injects a catastrophic clock failure */
} DIAG_CLOCK_FLTINJ_TYPE;


/**
 * @ingroup enums
 * @enum DIAG_CLOCK_MON_REF_CLK
 * @brief Enumerates the possible clock sources for both monitored and reference clocks.
 *
 * This enumeration is used to specify the clock source to be monitored or used as a reference
 * in the clock monitor diagnostic test.
 */
typedef enum
{
    DIAG_CLOCK_SERIAL_TEST_MODE_CLOCK, /**< Serial test mode clock */
    DIAG_CLOCK_FRC,                   /**< Fast RC oscillator */
    DIAG_CLOCK_BFRC,                  /**< Backup Fast RC oscillator */
    DIAG_CLOCK_POSC,                  /**< Primary oscillator */
    DIAG_CLOCK_LPRC,                  /**< Low-power RC oscillator */
    DIAG_CLOCK_PLL1_FOUT,             /**< PLL1 output */
    DIAG_CLOCK_PLL2_FOUT,             /**< PLL2 output */
    DIAG_CLOCK_PLL1_VCO,              /**< PLL1 VCO */
    DIAG_CLOCK_PLL2_VCO,              /**< PLL2 VCO */
    DIAG_CLOCK_REF2,                  /**< Reference clock 2 */
    DIAG_CLOCK_REF1                   /**< Reference clock 1 */
} DIAG_CLOCK_MON_REF_CLK;

/**
 * @ingroup enums
 * @enum DIAG_CLOCK_MON_INST
 * @brief Identifies the available clock monitor hardware instances.
 *
 * This enumeration is used to select which clock monitor instance is to be configured
 * and tested by the diagnostic function.
 */
typedef enum
{
    DIAG_CLOCK_MON_INSTANCE_1,      /**< Clock Monitor Instance 1 */
    DIAG_CLOCK_MON_INSTANCE_2,      /**< Clock Monitor Instance 2 */
    DIAG_CLOCK_MON_INSTANCE_3,      /**< Clock Monitor Instance 3 */
    DIAG_CLOCK_MON_INSTANCE_4,      /**< Clock Monitor Instance 4 */
    DIAG_CLOCK_MONITOR_MAX_INSTANCE/**< Maximum number of clock monitor instances (not a valid instance) */
} DIAG_CLOCK_MON_INST;

/**
 * @ingroup functions
 * @brief **Software Requirement Reference ID : SW_FAIL_SAFE_CLOCK_MONITOR_TEST**
 *   
 * Sets the clock monitor fault status.
 * @param   status The status value to set for clock fault injection.
 * @par
 * @details Updates the global clockFaultInjectStatus variable with the provided status value.
 */
void DIAG_CLOCK_SetClockMonFaultStatus(uint32_t status);

/**
 * @ingroup functions
 * @brief **Software Requirement Reference ID : SW_FAIL_SAFE_CLOCK_MONITOR_TEST**
 *  
 * Performs a failsafe clock monitor (FSCM) test by configuring a clock monitor instance,
 * injecting a specified clock fault, and verifying fault detection.
 *
 * This function sets up the selected clock monitor instance with the specified monitored and reference
 * clock sources, enables the monitor, waits for a valid buffer value, injects a chosen fault type,
 * and checks if the fault is detected within a timeout period. The result indicates whether the
 * fault was successfully detected by the hardware.
 *
 * @param[in] clkMonInstance
 *   The clock monitor instance to be tested. Possible values:
 *   - CLOCKMON_INSTANCE_1: Clock Monitor Instance 1
 *   - CLOCKMON_INSTANCE_2: Clock Monitor Instance 2
 *   - CLOCKMON_INSTANCE_3: Clock Monitor Instance 3
 *   - CLOCKMON_INSTANCE_4: Clock Monitor Instance 4
 *   - MAX_CLOCK_MONITOR_INSTANCE: Maximum number of clock monitor instances (not for use as a valid instance)
 *
 * @param[in] monClkSrc
 *   The clock source to be monitored. Possible values (also used for refClkSrc):
 *   - SERIAL_TEST_MODE_CLOCK: Serial test mode clock
 *   - FRC: Fast RC oscillator
 *   - BFRC: Backup Fast RC oscillator
 *   - POSC: Primary oscillator
 *   - LPRC: Low-power RC oscillator
 *   - PLL1_FOUT: PLL1 output
 *   - PLL2_FOUT: PLL2 output
 *   - PLL1_VCO: PLL1 VCO
 *   - PLL2_VCO: PLL2 VCO
 *   - REF2: Reference clock 2
 *   - REF1: Reference clock 1
 *
 * @param[in] refClkSrc
 *   The reference clock source against which the monitored clock is compared.
 *   Uses the same enum and possible values as @p monClkSrc.
 *
 * @param[in] fltinjType
 *   The type of fault to inject for testing the clock monitor's detection capability. Possible values:
 *   - CLOCK_LOW_FREQ_DRIFT_FLTINJ: Injects a low frequency drift fault
 *   - CLOCK_HIGH_FREQ_DRIFT_FLTINJ: Injects a high frequency drift fault
 *   - CLOCK_CATASTROPHIC_FLTINJ: Injects a catastrophic clock failure
 *
 * @return
 *   DIAG_PASS if the injected fault is detected by the clock monitor, DIAG_FAIL otherwise.
 *
 * @note
 *   - This function is blocking and will wait until either a fault is detected or the timeout expires.
 *   - The function manipulates hardware registers directly and should be used with care.
 *   - The enums DIAG_CLOCK_MON_INST, DIAG_CLOCK_MON_REF_CLK, and DIAG_CLOCK_FLTINJ_TYPE are defined in the relevant header.
 *
 * @see DIAG_CLOCK_SetClockMonFaultStatus
 *
 * Example usage:
 * @code
 * uint32_t result = DIAG_CLOCK_FscmTest(CLOCKMON_INSTANCE_1, FRC, POSC, CLOCK_LOW_FREQ_DRIFT_FLTINJ);
 * if (result == DIAG_PASS) {
 *     // Fault detected successfully
 * } else {
 *     // Fault not detected
 * }
 * @endcode
 @par 
Imageref DIAG_CLOCK_FscmTest_UML.svg "Clock Fail Safe Clock Monitor Sequence diagram"
Imageref DIAG_CLOCK_FscmTest_ClassDiagram.svg "Clock Fail Safe Clock Monitor Class diagram"
 */
uint32_t DIAG_CLOCK_FscmTest(DIAG_CLOCK_MON_INST clkMonInstance,
                            DIAG_CLOCK_MON_REF_CLK monClkSrc, 
                            DIAG_CLOCK_MON_REF_CLK refClkSrc,
                            DIAG_CLOCK_FLTINJ_TYPE fltinjType);

#endif /* DIAG_CLOCK_H */
