/**
 * ADC4 Generated Driver Source File
 * 
 * @file      adc4.c
 *            
 * @ingroup   adcdriver
 *            
 * @brief     This is the generated driver source file for ADC4 driver        
 *
 * @skipline @version   PLIB Version 1.2.1
 *           
 * @skipline  Device : dsPIC33AK512MPS506
*/

/*
? [2026] Microchip Technology Inc. and its subsidiaries.

    Subject to your compliance with these terms, you may use Microchip 
    software and any derivatives exclusively with Microchip products. 
    You are responsible for complying with 3rd party license terms  
    applicable to your use of 3rd party software (including open source  
    software) that may accompany Microchip software. SOFTWARE IS ?AS IS.? 
    NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS 
    SOFTWARE, INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT,  
    MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. 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 RELATED TO THE SOFTWARE WILL NOT 
    EXCEED AMOUNT OF FEES, IF ANY, YOU PAID DIRECTLY TO MICROCHIP FOR 
    THIS SOFTWARE.
*/

// Section: Included Files
#include <stddef.h>
#include "../adc4.h"

// Section: File specific functions

static void (*ADC4_ChannelHandler)(enum ADC4_CHANNEL channel, uint16_t adcVal) = NULL;
static void (*ADC4_Result32BitChannelHandler)(enum ADC4_CHANNEL channel, uint32_t adcVal) = NULL;
static void (*ADC4_ComparatorHandler)(enum ADC4_CMP comparator) = NULL;

// Section: File specific data type definitions

/**
 @ingroup  adcdriver
 @enum     ADC4_PWM_TRIG_SRCS
 @brief    Defines the PWM ADC TRIGGER sources available for the module to use.
*/
enum ADC4_PWM_TRIG_SRCS {
    PWM8_TRIGGER2 = 0x13, 
    PWM8_TRIGGER1 = 0x12, 
    PWM7_TRIGGER2 = 0x11, 
    PWM7_TRIGGER1 = 0x10, 
    PWM6_TRIGGER2 = 0xf, 
    PWM6_TRIGGER1 = 0xe, 
    PWM5_TRIGGER2 = 0xd, 
    PWM5_TRIGGER1 = 0xc, 
    PWM4_TRIGGER2 = 0xb, 
    PWM4_TRIGGER1 = 0xa, 
    PWM3_TRIGGER2 = 0x9, 
    PWM3_TRIGGER1 = 0x8, 
    PWM2_TRIGGER2 = 0x7, 
    PWM2_TRIGGER1 = 0x6, 
    PWM1_TRIGGER2 = 0x5, 
    PWM1_TRIGGER1 = 0x4, 
};

//Defines an object for ADC_MULTICORE.
static const struct ADC_MULTICORE adc4Multicore = {
    .ChannelSoftwareTriggerEnable           = &ADC4_ChannelSoftwareTriggerEnable,
    .ChannelSoftwareTriggerDisable          = &ADC4_ChannelSoftwareTriggerDisable,
    .SampleCountGet                         = NULL,
    .SampleCountStatusGet                   = NULL,
    .ChannelTasks                           = &ADC4_ChannelTasks, 
    .ComparatorTasks                        = NULL,
    .IndividualChannelInterruptEnable       = &ADC4_IndividualChannelInterruptEnable,
    .IndividualChannelInterruptDisable      = &ADC4_IndividualChannelInterruptDisable,
    .IndividualChannelInterruptFlagClear    = &ADC4_IndividualChannelInterruptFlagClear,
    .IndividualChannelInterruptPrioritySet  = &ADC4_IndividualChannelInterruptPrioritySet,
    .ChannelCallbackRegister                = &ADC4_ChannelCallbackRegister,
    .Result32BitChannelCallbackRegister     = &ADC4_Result32BitChannelCallbackRegister,
    .ComparatorCallbackRegister             = &ADC4_ComparatorCallbackRegister,
    .CorePowerEnable                        = NULL,
    .SharedCorePowerEnable                  = &ADC4_SharedCorePowerEnable,
    .CoreCalibration                        = NULL,
    .SharedCoreCalibration                  = &ADC4_SharedCoreCalibration,
    .PWMTriggerSourceSet                    = &ADC4_PWMTriggerSourceSet
};

//Defines an object for ADC_INTERFACE.

const struct ADC_INTERFACE ADC4 = {
    .Initialize             = &ADC4_Initialize,
    .Deinitialize           = &ADC4_Deinitialize,
    .Enable                 = &ADC4_Enable,
    .IsReady                = &ADC4_IsReady,
    .Disable                = &ADC4_Disable,
    .SoftwareTriggerEnable  = &ADC4_SoftwareTriggerEnable,
    .SoftwareTriggerDisable = &ADC4_SoftwareTriggerDisable,
    .ChannelSelect          = NULL, 
    .ConversionResultGet    = &ADC4_ConversionResultGet,
    .SecondaryAccumulatorGet= NULL,
    .IsConversionComplete   = &ADC4_IsConversionComplete,
    .ResolutionSet          = NULL,
    .InterruptEnable        = NULL,
    .InterruptDisable       = NULL,
    .InterruptFlagClear     = NULL,
    .InterruptPrioritySet   = NULL,
    .CommonCallbackRegister = NULL,
    .Tasks                  = NULL,
    .adcMulticoreInterface = &adc4Multicore,
};

// Section: Driver Interface Function Definitions

void ADC4_Initialize(void)
{
    //CALCNT Wait for 2 activity free ADC clock cycles; BUFEN disabled; TSTEN disabled; ON enabled; STNDBY disabled; RPTCNT 1 ADC clock cycles between triggers; CALRATE Every second; ACALEN disabled; CALREQ Calibration cycle is not requested; 
    AD4CON = (uint32_t)0x8000UL & ~_AD1CON_ON_MASK;
    //DATAOVR 0x0; 
    AD4DATAOVR = 0x0UL;
    //CH0RDY disabled; CH1RDY disabled; CH2RDY disabled; CH3RDY disabled; CH4RDY disabled; CH5RDY disabled; CH6RDY disabled; CH7RDY disabled; 
    AD4STAT = 0x0UL;
    //CH0RRDY disabled; CH1RRDY disabled; CH2RRDY disabled; CH3RRDY disabled; CH4RRDY disabled; CH5RRDY disabled; CH6RRDY disabled; CH7RRDY disabled; 
    AD4RSTAT = 0x0UL;
    //CH0CMP disabled; CH1CMP disabled; CH2CMP disabled; CH3CMP disabled; CH4CMP disabled; CH5CMP disabled; CH6CMP disabled; CH7CMP disabled; 
    AD4CMPSTAT = 0x0UL;
    //CH0TRG disabled; CH1TRG disabled; CH2TRG disabled; CH3TRG disabled; CH4TRG disabled; CH5TRG disabled; CH6TRG disabled; CH7TRG disabled; 
    AD4SWTRG = 0x0UL;
    //TRG1SRC Software trigger initiated by using ADnSWTRG register; MODE Single sample initiated by TRG1SRC[4:0] trigger; TRG2SRC Triggers are disabled; ACCNUM 4 samples, 13 bits result; SAMC 0.5 TAD; IRQSEL enabled; EIEN disabled; TRG1POL disabled; PINSEL AD4AN1; NINSEL disabled; FRAC Integer; DIFF disabled; 
    AD4CH0CON1 = 0x1200001UL;
    //ADCMPCNT disabled; CMPMOD NONE; CMPCNTMOD disabled; CMPVAL enabled; ACCBRST disabled; ACCRO disabled; 
    AD4CH0CON2 = 0x20000000UL;
    //
    AD4CH0RES = 0x0UL;
    //CNT 0x0; 
    AD4CH0CNT = 0x0UL;
    //CMPLO 0x0; 
    AD4CH0CMPLO = 0x0UL;
    //CMPHI 0x0; 
    AD4CH0CMPHI = 0x0UL;

    ADC4_ChannelCallbackRegister(&ADC4_ChannelCallback);
    ADC4_Result32BitChannelCallbackRegister(&ADC4_Result32BitChannelCallback);
    ADC4_ComparatorCallbackRegister(&ADC4_ComparatorCallback);
    
    
    // ADC Mode change to run mode
    ADC4_SharedCorePowerEnable();
}

void ADC4_Deinitialize (void)
{
    AD4CONbits.ON = 0U;
    
    AD4CON = 0x480000UL;
    AD4DATAOVR = 0x0UL;
    AD4STAT = 0x0UL;
    AD4RSTAT = 0x0UL;
    AD4CMPSTAT = 0x0UL;
    AD4SWTRG = 0x0UL;
    AD4CH0CON1 = 0x0UL;
    AD4CH0CON2 = 0x1UL;
    AD4CH0RES = 0x0UL;
    AD4CH0CNT = 0x0UL;
    AD4CH0CMPLO = 0x0UL;
    AD4CH0CMPHI = 0x0UL;
}

void ADC4_SharedCorePowerEnable (void) 
{
    AD4CONbits.ON = 1U;   
    while(AD4CONbits.ADRDY == 0U)
    {
    }
}

void ADC4_SharedCoreCalibration (void) 
{
    AD4CONbits.CALREQ = 1U;    
    while(AD4CONbits.CALRDY == 0U)
    {
    }  
}

static uint16_t ADC4_TriggerSourceValueGet(enum ADC_PWM_INSTANCE pwmInstance, enum ADC_PWM_TRIGGERS triggerNumber)
{
    uint16_t adcTriggerSourceValue = 0x0U;
    switch(pwmInstance)
    {
        case ADC_PWM_GENERATOR_8:
                if(triggerNumber == ADC_PWM_TRIGGER_1)
                {
                    adcTriggerSourceValue = PWM8_TRIGGER1;
                }
                else if(triggerNumber == ADC_PWM_TRIGGER_2)
                {
                    adcTriggerSourceValue = PWM8_TRIGGER2;
                }
                else
                {
                }
                break;
        case ADC_PWM_GENERATOR_7:
                if(triggerNumber == ADC_PWM_TRIGGER_1)
                {
                    adcTriggerSourceValue = PWM7_TRIGGER1;
                }
                else if(triggerNumber == ADC_PWM_TRIGGER_2)
                {
                    adcTriggerSourceValue = PWM7_TRIGGER2;
                }
                else
                {
                }
                break;
        case ADC_PWM_GENERATOR_6:
                if(triggerNumber == ADC_PWM_TRIGGER_1)
                {
                    adcTriggerSourceValue = PWM6_TRIGGER1;
                }
                else if(triggerNumber == ADC_PWM_TRIGGER_2)
                {
                    adcTriggerSourceValue = PWM6_TRIGGER2;
                }
                else
                {
                }
                break;
        case ADC_PWM_GENERATOR_5:
                if(triggerNumber == ADC_PWM_TRIGGER_1)
                {
                    adcTriggerSourceValue = PWM5_TRIGGER1;
                }
                else if(triggerNumber == ADC_PWM_TRIGGER_2)
                {
                    adcTriggerSourceValue = PWM5_TRIGGER2;
                }
                else
                {
                }
                break;
        case ADC_PWM_GENERATOR_4:
                if(triggerNumber == ADC_PWM_TRIGGER_1)
                {
                    adcTriggerSourceValue = PWM4_TRIGGER1;
                }
                else if(triggerNumber == ADC_PWM_TRIGGER_2)
                {
                    adcTriggerSourceValue = PWM4_TRIGGER2;
                }
                else
                {
                }
                break;
        case ADC_PWM_GENERATOR_3:
                if(triggerNumber == ADC_PWM_TRIGGER_1)
                {
                    adcTriggerSourceValue = PWM3_TRIGGER1;
                }
                else if(triggerNumber == ADC_PWM_TRIGGER_2)
                {
                    adcTriggerSourceValue = PWM3_TRIGGER2;
                }
                else
                {
                }
                break;
        case ADC_PWM_GENERATOR_2:
                if(triggerNumber == ADC_PWM_TRIGGER_1)
                {
                    adcTriggerSourceValue = PWM2_TRIGGER1;
                }
                else if(triggerNumber == ADC_PWM_TRIGGER_2)
                {
                    adcTriggerSourceValue = PWM2_TRIGGER2;
                }
                else
                {
                }
                break;
        case ADC_PWM_GENERATOR_1:
                if(triggerNumber == ADC_PWM_TRIGGER_1)
                {
                    adcTriggerSourceValue = PWM1_TRIGGER1;
                }
                else if(triggerNumber == ADC_PWM_TRIGGER_2)
                {
                    adcTriggerSourceValue = PWM1_TRIGGER2;
                }
                else
                {
                }
                break;
         default:
                break;
    }
    return adcTriggerSourceValue;
}

void ADC4_PWMTriggerSourceSet(enum ADC4_CHANNEL channel, enum ADC_PWM_INSTANCE pwmInstance, enum ADC_PWM_TRIGGERS triggerNumber)
{
    uint16_t adcTriggerValue;
    adcTriggerValue= ADC4_TriggerSourceValueGet(pwmInstance, triggerNumber);
    switch(channel)
    {
        case ADC4_Channel0:
                AD4CH0CON1bits.TRG1SRC = adcTriggerValue;
                break;
        default:
                break;
    }
}

void ADC4_ChannelCallbackRegister(void(*callback)(enum ADC4_CHANNEL channel, uint16_t adcVal))
{
    if(NULL != callback)
    {
        ADC4_ChannelHandler = callback;
    }
}

void __attribute__ ( ( weak ) ) ADC4_ChannelCallback (enum ADC4_CHANNEL channel, uint16_t adcVal)
{ 
    (void)channel;
    (void)adcVal;
} 

void ADC4_Result32BitChannelCallbackRegister(void(*callback)(enum ADC4_CHANNEL channel, uint32_t adcVal))
{
    if(NULL != callback)
    {
        ADC4_Result32BitChannelHandler = callback;
    }
}

void __attribute__ ( ( weak ) ) ADC4_Result32BitChannelCallback (enum ADC4_CHANNEL channel, uint32_t adcVal)
{ 
    (void)channel;
    (void)adcVal;
} 


/* cppcheck-suppress misra-c2012-8.4
*
* (Rule 8.4) REQUIRED: A compatible declaration shall be visible when an object or 
* function with external linkage is defined
*
* Reasoning: Interrupt declaration are provided by compiler and are available
* outside the driver folder
*/
void __attribute__ ( ( __interrupt__, weak ) ) _AD4CH0Interrupt ( void )
{
    uint32_t valADC4_Channel0;
    //Read the ADC value from the ADCBUF
    valADC4_Channel0 = AD4CH0DATA;

    if(NULL != ADC4_ChannelHandler)
    {
        (*ADC4_ChannelHandler)(ADC4_Channel0, valADC4_Channel0);
    }
    if(NULL != ADC4_Result32BitChannelHandler)
    {
        (*ADC4_Result32BitChannelHandler)(ADC4_Channel0, valADC4_Channel0);
    }

    //clear the ADC4_Channel0 interrupt flag
    IFS6bits.AD4CH0IF = 0U;
}


void __attribute__ ( ( weak ) ) ADC4_ChannelTasks (enum ADC4_CHANNEL channel)
{
    uint32_t adcVal;
    
    switch(channel)
    {   
        case ADC4_Channel0:
            if((bool)AD4STATbits.CH0RDY == 1U)
            {
                //Read the ADC value from the ADCBUF
                adcVal = AD4CH0DATA;

                if(NULL != ADC4_ChannelHandler)
                {
                    (*ADC4_ChannelHandler)(channel, adcVal);
                }
                if(NULL != ADC4_Result32BitChannelHandler)
                {
                    (*ADC4_Result32BitChannelHandler)(channel, adcVal);
                }
            }
            break;
        default:
            break;
    }            
}

void ADC4_ComparatorCallbackRegister(void(*callback)(enum ADC4_CMP comparator))
{
    if(NULL != callback)
    {
        ADC4_ComparatorHandler = callback;
    }
}

void __attribute__ ( ( weak ) ) ADC4_ComparatorCallback (enum ADC4_CMP comparator)
{ 
    (void)comparator;
} 



