/**
*   @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_gpio.h
 *  @version    1.0
 *  @brief      This file has the declarations for the GPIO diagnostic 
 *              functions
 *
 *************************************************************************/
/**
 @defgroup functions Functions
 @defgroup macros Macros
*/
#ifndef DIAG_PORTS_H
#define DIAG_PORTS_H

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

/* Port Register Macros */
/**
 @ingroup macros
 @def PORTA_PTR
 This macro automatically maps the PORTA address of the device from the device header.
*/
#define     PORTA_PTR   &PORTA
         
/**
 @ingroup macros
 @def PORTB_PTR
 This macro automatically maps the PORTB address of the device from the device header.
*/
#define     PORTB_PTR   &PORTB
         
/**
 @ingroup macros
 @def PORTC_PTR
 This macro automatically maps the PORTC address of the device from the device header.
*/
#define     PORTC_PTR   &PORTC
         
/**
 @ingroup macros
 @def PORTD_PTR
 This macro automatically maps the PORTD address of the device from the device header.
*/
#define     PORTD_PTR   &PORTD
         
/**
 @ingroup macros
 @def PORTE_PTR
 This macro automatically maps the PORTE address of the device from the device header.
*/
#define     PORTE_PTR   &PORTE
         
/**
 @ingroup macros
 @def PORTF_PTR
 This macro automatically maps the PORTF address of the device from the device header.
*/
#define     PORTF_PTR   &PORTF
         
/**
 @ingroup macros
 @def PORTG_PTR
 This macro automatically maps the PORTG address of the device from the device header.
*/
#define     PORTG_PTR   &PORTG
         
/**
 @ingroup macros
 @def PORTH_PTR
 This macro automatically maps the PORTH address of the device from the device header.
*/
#define     PORTH_PTR   &PORTH
/**
 @ingroup macros
 @def DIAG_GPIO_IOIM_INSTANCES
 This macro indicates the number of instances of IO integrity monitor module.
*/        
#define DIAG_GPIO_IOIM_INSTANCES 16U

/* Function Declarations */
/**
 * @ingroup functions
 *  @brief **Software Requirement Reference ID : SW_GPIO_PORTS_INPUT_PRACTICE_01**\n
 * External connections between two input configured pins ensures that both of them
 receive the same input.  This diagnostic compares the state of these two
 pins (PORTx bit) and reports the result.  The Hardware requirement 
 HW_IO_INPUT_SECONDARY_IO_INPUT has to be met for this diagnostic
 to function.
 @param priInputPort - The PORT register to which the primary input pin belongs to
 @param priInputPin - Pin number on the priInputPort that is physically accessed
 @param secInputPort - The PORT register to which the secondary input pin belongs to
 @param secInputPin - Pin number on the secInputPort that is physically accessed
 @returns DIAG_PASS/DIAG_FAIL/DIAG_INVALID_PARAM  
 @par Code Snippet
 @code
  uint32_t Test_GPIO_InputPractice()
{
    uint32_t testResult;   
    _TRISC7 = 1;
    _TRISB11 = 1;
    _ANSELC7 = 0;
    _ANSELB11 = 0;
    _RC7 = 1;
    testResult = DIAG_GPIO_InputPractice((uint32_t*)PORTC_PTR, 7, 
                    (uint32_t*)PORTB_PTR, 11);
       
 * }
 @endcode
 @par
 Imageref DIAG_GPIO_InputPractice_UML.svg "GPIO Input Practice Sequence diagram"
 Imageref DIAG_GPIO_InputPractice_ClassDiagram.svg "GPIO Input Practice Class diagram"
 */                          
uint32_t DIAG_GPIO_InputPractice(uint32_t* priInputPort, uint16_t priInputPin,
                                uint32_t* secInputPort, uint16_t secInputPin); 
/**
 @ingroup functions
 @brief **Software Requirement Reference ID : SW_GPIO_PORTS_OUTPUT_TEST_01**\n
 Implements the comparison of the LATx and PORTx bits of the ports and reports
 the result of this comparison.  The Hardware requirement HW_IO_OUTPUT_IO_INPUT 
 has to be met for this diagnostic to function.
 @param outputPort - The PORT register to which the output pin belongs to
 @param outputPinNum - Pin number on the outputPort that is physically accessed
 @param inputPort - The PORT register to which the input pin belongs to
 @param inputPinNum - Pin number on the inputPort that is physically connected to 
 outputPinNum
 @returns DIAG_PASS/DIAG_FAIL/DIAG_INVALID_PARAM  
 @par Code Snippet
 @code
  uint32_t Test_GPIO_OutputTest()
{
    uint32_t testResult;
    _TRISF1 = 0;
    _TRISD5 = 1;
    _ANSELF1 = 0;
    _ANSELD5 = 0;
    _TRISC8 = 0;//led0
    testResult = DIAG_GPIO_OutputTest((uint32_t*)PORTF_PTR, 1, 
                    (uint32_t*)PORTD_PTR, 5);
       
 * }
 @endcode
 @par
 Imageref DIAG_GPIO_OutputTest_UML.svg "GPIO Output Test Sequence diagram"
 Imageref DIAG_GPIO_OutputTest_ClassDiagram.svg "GPIO Output Test Class diagram"
 */
uint32_t DIAG_GPIO_OutputTest(uint32_t* outputPort, uint16_t outputPinNum,
                                uint32_t* inputPort, uint16_t inputPinNum);
/**
 @ingroup functions
 @brief **Software Requirement Reference ID : SW_GPIO_ACTIVITY_CHECK_01**\n
 The diagnostic API shall accept the port and pin number of the I/O output pin
 to be tested and a reference I/O input pin. The activity on the output pin shall
 be connected to the input pin externally. 
 @param inputPort - The PORT register to which the input pin belongs to
 @param inputPinNum - Pin number on the inputPort that is physically connected to the 
 output pin under test.
 @param outputActivityFunc() - Function pointer, where user shall handle the output pin activity
 @param timeout - the diagnostic shall wait for timeout amount of time for the CN flag to be set, 
 this is in terms microseconds. 
 @returns DIAG_PASS/DIAG_FAIL/DIAG_INVALID_PARAM 
 @par Code Snippet
 @code
  void trig_gpioActivityCheck()
{
    //perform activity on output pin under test
}
  uint32_t Test_GPIO_ActivityCheck()
{
    uint32_t testResult;
   _TRISD6 = 0;
    _ANSELD6 = 0;

     _TRISF0 = 1;
    _ANSELF0 = 0;

    _CNEN0F0 = 1;
    _CNEN1F0 = 1;
    _CNFF0 = 0;
    CNCONFbits.CNSTYLE = 1;    //Config for PORTF
    CNCONFbits.ON = 1; 
    testResult = DIAG_GPIO_ActivityCheck((uint32_t*)PORTF_PTR, 0, 
            trig_gpioActivityCheck, 5);      
 * }
 @endcode
 @par
 Imageref DIAG_GPIO_ActivityCheck_UML.svg "GPIO Activity Check Sequence diagram"
 Imageref DIAG_GPIO_ActivityCheck_ClassDiagram.svg "GPIO Activity Check Class diagram"
 */
uint32_t DIAG_GPIO_ActivityCheck(uint32_t* inputPort, uint16_t inputPinNum, 
                        void (*outputActivityFunc)(), uint16_t timeout);
/**
 @ingroup functions
 @brief **Software Requirement Reference ID : SW_GPIO_PORTS_INTERRUPT_GENERATION_TEST_01**\n
 The diagnostic API shall accept the port address and pin number of input pin to be tested 
 and a reference output pin for testing. The two pins shall be connected externally. 
 Any transition on the output pin should generate a change notification ISR on the input pin.
 @param inputPort - The PORT register to which the input pin belongs to
 @param inputPinNum - Pin number on the inputPort that is physically connected to 
 outputPinNum
 @param outputPort - The PORT register to which the output pin belongs to
 @param outputPinNum - Pin number on the outputPort that is physically accessed
 @returns DIAG_PASS/DIAG_FAIL/DIAG_INVALID_PARAM 
 @par Code Snippet
 @code
 uint32_t Test_GPIO_IntrGenTest()
 {
    uint32_t testResult;
    _TRISC6 = 1;
    _ANSELC6 = 0;
    _TRISG0 = 0;
    _ANSELG0 = 0;

    _CNEN0C6 = 1;
    _CNEN1C6 = 1;
    _CNFC6 = 0;
    CNCONCbits.CNSTYLE = 1;    //Config for PORTC
    CNCONCbits.ON = 1;
    testResult = DIAG_GPIO_InterruptGenTest((uint32_t*)PORTC_PTR, 6, 
                            (uint32_t*)PORTG_PTR, 0);     
 * }
 @endcode 
 @par
 Imageref DIAG_GPIO_InterruptGen_UML.svg "GPIO Interrupt Generation Test Sequence diagram"
 Imageref DIAG_GPIO_InterruptGen_ClassDiagram.svg "GPIO Interrupt Generation Test Class diagram"
 */
uint32_t DIAG_GPIO_InterruptGenTest(uint32_t* inputPort, uint16_t inputPinNum, 
                uint32_t* outputPort, uint16_t outputPinNum);
/**
 @ingroup functions
 @brief **Software Requirement Reference ID : SW_GPIO_PPS_OUTPUT_CONNECTION_TEST_01**\n
 The diagnostic shall require the user to map the output pin under test to the peripheral
 of interest. The output pin under test shall also be connected to an input test pin. 
 Any activity through the peripheral should be reflected on the input test pin to verify
 the PPS of the output pin under test. 
 @param outputPort - The PORT register to which the output pin belongs to
 @param outputPinNum - Pin number on the outputPort that is physically accessed
 @param inputPort - The PORT register to which the input pin belongs to
 @param inputPinNum - Pin number on the inputPort that is physically connected to 
 outputPinNum
 @param outputPpsFunc() - Function pointer that shall trigger peripheral events on the pin 
 @param timeout - the diagnostic shall wait for timeout amount of time before comparing the logic states, 
 this is in terms microseconds
 @returns DIAG_PASS/DIAG_FAIL/DIAG_INVALID_PARAM
 @par Code Snippet
 @code
 * void test_ppsOutputTest()
 *{
 *  //perform peripheral activity
 *}
 * uint32_t Test_GPIO_PpsOutputTest()
 * {
 *    uint32_t testResult;
 *    testResult = DIAG_GPIO_PpsOutputConnectionTest((uint32_t*)PORTG_PTR, 5,
                                        (uint32_t*)PORTB_PTR, 12, test_ppsOutputTest, 5);     
 * }
 @endcode 
 @par
 Imageref DIAG_GPIO_OutputPpsTest_UML.svg "GPIO PPS Output Connection Test Sequence diagram"
 Imageref DIAG_GPIO_OutputPpsTest_ClassDiagram.svg "GPIO PPS Output Connection Test Class diagram"
 */
uint32_t DIAG_GPIO_PpsOutputConnectionTest(uint32_t* outputPort, uint16_t outputPinNum,
                                uint32_t* inputPort, uint16_t inputPinNum, void (*outputPpsFunc)(), uint16_t timeout);
/**
 @ingroup functions
 @brief **Software Requirement Reference ID : SW_IO_MONITOR_TEST_01**\n
 The diagnostic shall check the functionality of the module by using the
 OKINJ and FLTINJ,self-test feature of IOIM module.
 @returns DIAG_PASS/DIAG_FAIL
 @par Code Snippet
 @code
 * void __attribute__((interrupt, no_auto_psv)) _IOIMxInterrupt(void)
 *  {
 *   _IOMxIF = 0; // clear interrupt flag
    }
 * uint32_t Test_IOIM_Test()
 * {
 *    uint32_t testResult;
 *    uint32_t testStatus;
 *    testResult = DIAG_GPIO_IntegrityMonitorTest(void); 
 *    if(testResult == DIAG_FAIL)
      {
        testStatus = DIAG_GPIO_IOIM_GetStatus(void);    
      }
 @endcode
 @par
 Imageref DIAG_GPIO_IntegrityMonitor_UML.svg "GPIO Integrity Monitor Sequence diagram"
 Imageref DIAG_GPIO_IntegrityMonitor_ClassDiagram.svg "GPIO Integrity Monitor Class diagram"
 */
uint32_t DIAG_GPIO_IntegrityMonitorTest(void);
/**
 @ingroup functions
 @brief 
 The API shall return the status variable of @ref DIAG_GPIO_IntegrityMonitorTest diagnostic.
 @returns DIAG_GPIO_IoimInstResult
 @par
 */
uint32_t DIAG_GPIO_IOIM_GetStatus(void);
#endif /* DIAG_PORTS_H */
