
//##############################################################################
//    filename:        MCP4822.c
// ##############################################################################
//    LCD library for MCP4822 SPI DAC
//##############################################################################
//      Author:            	P.Prosser
//      Company:        	
//      Adapted:            AS
//      Revision:           0.0 (for XC32)
//      Date:         	    Aug 2024
//     	Compiler            XC32 
//      MPLAB X             
//      MCC                 
//##############################################################################


#include "Inductor_Tester_Meas.h"
#include <assert.h>
#include "Inductor_Tester.h"
#include "definitions.h"
#include <xc.h>            
#include <sys/attribs.h> 
#include "MCP4822.h"
#include "sys/kmem.h"
#include "peripheral/coretimer/plib_coretimer.h"


//#############################################################################
//
//  Discharge_DUT
//
//#############################################################################
void Discharge_DUT() {
    int Time_Cnt, Discharge_Duration;
           
    /* start with discharge rate minimum and discharge inactibe*/
    Discharge_Inactive;
    Discharge_Duration = 0;
    for(Time_Cnt = 0; Time_Cnt < Discharge_Time_Ms; Time_Cnt++) {
        Discharge_Duration = (Time_Cnt * 1000)/Discharge_Time_Ms;
        if ((Discharge_Duration > 0) && (Discharge_Duration < 1000)) {
            Discharge_Active;
            CORETIMER_DelayUs (Discharge_Duration);
            Discharge_Inactive;
            CORETIMER_DelayUs (1000-Discharge_Duration);
        }
    };
    
    /* ensure this is clear! */
    Discharge_Inactive;
    /* now pause long enough for the discharge circuit to be fully inactive*/
    /* This need only be 50 or so mS - add some margin for component tolerances*/
//    CORETIMER_DelayMs (Discharge_Recovery_Time_Ms);
}

//#############################################################################
//
//  Short_DUT  - shorts DUT for 1mS
//      ASSUMES there is not significant charge on the DUT
//      Leaves DUT Un Shorted
//
//#############################################################################
void Short_DUT_1ms() {
           
    /* start with discharge rate minimum and discharge inactibe*/
    Discharge_Active;
    CORETIMER_DelayMs (Short_Duration);
    Discharge_Inactive;
    CORETIMER_DelayUs (Short_Latency);
}

//#############################################################################
//
//  Short_DUT  - Leaves it shorted
//      ASSUMES there is not significant charge on the DUT
//
//#############################################################################
void Short_DUT() {
           
    /* start with discharge rate minimum and discharge inactibe*/
    Discharge_Inactive;
    Discharge_Active;
}


//#############################################################################
//
//  Un Short_DUT  - Leaves it open
//
//#############################################################################
void Un_Short_DUT() {
           
    /* start with discharge rate minimum and discharge inactibe*/
    Discharge_Inactive;
}


//#############################################################################
//
//  Initialise_Pulser
//
//#############################################################################
void  Initialise_Pulser() {
    /* lets clock a low through to the Pulser*/
    Pulser_CLK_Lo;
    CORETIMER_DelayUs (Pulser_Time);
    Pulser_D_Lo;
    CORETIMER_DelayUs (Pulser_Time);
    Pulser_CLK_Hi;
    CORETIMER_DelayUs (Pulser_Time);
    Pulser_CLK_Lo;
    CORETIMER_DelayUs (Pulser_Time);


    
    
        Pulser_CLK_Lo;
    CORETIMER_DelayUs (Pulser_Time);
    Pulser_D_Hi;
    CORETIMER_DelayUs (Pulser_Time);
    Pulser_CLK_Hi;
    CORETIMER_DelayUs (Pulser_Time);
    Pulser_CLK_Lo;
    CORETIMER_DelayUs (Pulser_Time);



}


//#############################################################################
//
//  Trigger_Pulser
//  Assumes that the cutoff current is set
//  Assumes that the current sense will switch this off at the limit
//
//#############################################################################
void Pulse_Start() {
    /* lets clock a low through to the Pulser*/
    Pulser_CLK_Lo;
    CORETIMER_DelayUs (Pulser_Time);
    Pulser_D_Hi;
    CORETIMER_DelayUs (Pulser_Time);
    Pulser_CLK_Hi;                      /* Clocks the Pulse output through */
//    CORETIMER_DelayUs (Pulser_Time);
    Pulser_CLK_Lo;
    /* now assumes that this will be switched off by the current sense */
}


//#############################################################################
//
//  Trigger_Pulser with timeout shutdown
//  Assumes that the cutoff current is set
//  Implements timeout with the delay in microsconds
//
//#############################################################################
void Pulse_Start_With_Timeout(int Max_Pulse_Time) {
    /* lets clock a low through to the Pulser*/
    Pulser_CLK_Lo;
    CORETIMER_DelayUs (Pulser_Time);
    Pulser_D_Hi;
    CORETIMER_DelayUs (Pulser_Time);
    Pulser_CLK_Hi;                      /* Clocks the Pulse output through */
    CORETIMER_DelayUs (Max_Pulse_Time);
    Pulser_CLK_Lo;
    Pulser_D_Lo;
    Pulser_CLK_Hi;                      /* Clocks Pulse output Low */
    /* Normal operation would have the current sense RESET the fET */
}


//#############################################################################
//
//  Clear Test Current
//  Sets a test current through the DUT for initial phase measurements
//
//#############################################################################
void Clear_Test_Current() {
    /* Set output of MCP4822 to zero volts*/
    
    MCP4822_setVoltage(DUT_Measurement_Channel, Zero_Current_Output);
    
}

//#############################################################################
//
//  Set Test Current
//  Sets a test current through the DUT for initial phase measurements
//
//#############################################################################
void Set_Test_Current(float Current_Set) {
    float Vout_To_Set;
    
    // Want the DAC Vout = Current_Set * Test_Current_Resistor
    // DAC value = Current_Set * Test_Current_Resistor * DAC_Full_Scale

    Vout_To_Set = Current_Set * LTestData.Test_Current_Resistor;
    if ((Vout_To_Set) < 0)
        Vout_To_Set = 0;
    if (Vout_To_Set > LTestData.DAC_Full_Scale_V)
        Vout_To_Set = LTestData.DAC_Full_Scale_V;

    /* now write to the DAC */
    MCP4822_setVoltage(DUT_Measurement_Channel, Vout_To_Set);

 }


//#############################################################################
//
//  Set Test Inductor Current Cutoff
//  Sets the maximum (cutodff) current through the DUT
//
// Current Sense Resistor is nominally 0.005 Ohms
//      defined in LTestData.Current_Meas_Resistor
//      Need to see whether to cal this or simply uise as is
// Current Sense Amplifier is nominally 20 times gain 
//      #define Current_Sense_Gain 20
//
// Sense voltage = LTestData.Current_Meas_Resistor * Current_Sense_Gain * LTestData.Current_Meas_Resistor
//#############################################################################
void Set_Cutoff_Current(float Current_Set) {
    float Vout_To_Set;
    
    /* This somes out as 0.1 Volt per amp */
    Vout_To_Set = Current_Set * LTestData.Current_Meas_Resistor * Current_Sense_Gain;
    /* Apply Cal Factor*/
    Vout_To_Set = Vout_To_Set * LTestData.ICutoff_DAC_Cal;
    /* it will be a bad day if this code catches an error, but this is the right thing to add*/
    if (Vout_To_Set < 0)
        Vout_To_Set = 0;
    else if (Vout_To_Set > LTestData.DAC_Full_Scale_V)
        Vout_To_Set = LTestData.DAC_Full_Scale_V;

    /* now write to the DAC current cutoff channel*/
    MCP4822_setVoltage(Current_Cutoff_Channel, Vout_To_Set);
}

//#############################################################################
//
//  Clear Inductor Current Cutoff - for completeness
//
//#############################################################################
void Clear_Cutoff_Current() {
    /* now write to the DAC current cutoff channel*/
    MCP4822_setVoltage(Current_Cutoff_Channel, 0.0);
}


/***********************************************************************/
/* Read ADC channel as demanded                                        */
/*      input: Voltage source to be measured                           */
/*      Waits to see ADC Read is complete                              */
/*      Then dumps requested data into LTestData.ADC_CH0[] array in V  */
/* Selecting the ADC input to use is requires us to set:              */
/*      Select analog input for ADC modules                            */
/*    ADCTRGMODEbits.SH0ALT = 0; // ADC0 = AN0                         */
/*    ADCTRGMODEbits.SH1ALT = 0; // ADC1 = AN1                         */
/*    ADCTRGMODEbits.SH2ALT = 0; // ADC2 = AN2                         */
/*    on the PIC32MK0128 48 pin device this is                         */
/* bit 19-18 SH1ALT<1:0>: ADC1 Analog Input Select bit                 */
/*      11 = AN16(1)                                                    */
/*      10 = AN5(1)                                                    */
/*      01 = AN3(1)                                                    */
/*      00 = AN1                                                       */
/* bit 17-16 SH0ALT<1:0>: ADC0 Analog Input Select bit                 */
/*      11 = AN6(1)                                                    */
/*      10 = AN4(1)                                                    */
/*      01 = AN13                                                      */
/*      00 = AN0                                                       */
/*                                                                     */
/*  Voltage Sense = AN0 = ADC0, SH0ALT = 00                            */
/*  Resistance Low Gain = ADC0, SH0ALT = 01                            */
/*  Resistance Hi Gain  = ADC0, SH0ALT = 11                            */
/*                                                                     */
/*  Inductor Current MEasurement = ADC1, SH1ALT = 00                   */
/***********************************************************************/
void Select_ADC0_Input_To_Read(int Input_To_Read) {

    if (Input_To_Read == ADC0_Voltage_Sense_Channel_Select)
        ADCTRGMODEbits.SH0ALT = ADC0_Voltage_Sense_Channel_Select;
    else if (Input_To_Read == ADC0_Resistance_Low_Gain_Channel_Select)
        ADCTRGMODEbits.SH0ALT = ADC0_Resistance_Low_Gain_Channel_Select;
    else if (Input_To_Read == ADC0_Resistance_Hi_Gain_Channel_Select)
        ADCTRGMODEbits.SH0ALT = ADC0_Resistance_Hi_Gain_Channel_Select;
    else;
}

void Select_ADC1_Input_To_Read(int Input_To_Read) {

    if (Input_To_Read == ADC1_Inductor_Current_Channel_Select)
        ADCTRGMODEbits.SH1ALT = ADC1_Inductor_Current_Channel_Select;
    else;

}


/************************************************************************/
/*  Lets make this easy for me                                          */
/*      Measure voltage across current sense resistor                   */
/************************************************************************/
void Measure_Current_Sense_Voltage()
{
    Select_ADC1_Input_To_Read(ADC1_Inductor_Current_Channel_Select);
}

/************************************************************************/
/*  Lets make this easy for me                                          */
/*      Measure the nominal 10V rail voltage                            */
/************************************************************************/
void Measure_Test_Voltage_Rail()
{
    Select_ADC0_Input_To_Read(ADC0_Voltage_Sense_Channel_Select);
}

/************************************************************************/
/*  Lets make this easy for me                                          */
/*      Measure DUT Voltage Low Gain                                    */
/*      This actually just measures voltage and might be used for       */
/*      a multitude of other measurements.... so lest rename voltage    */
/************************************************************************/
void Measure_DUT_Voltage_Low_Gain()
{
    Select_ADC0_Input_To_Read(ADC0_Resistance_Low_Gain_Channel_Select);
}

/************************************************************************/
/*  Lets make this easy for me                                          */
/*      Measure DUT Voltage High Gain                                   */
/*      This actually just measures voltage and might be used for       */
/*      a multitude of other measurements.... so lest rename voltage    */
/************************************************************************/
void Measure_DUT_Voltage_High_Gain()
{
    Select_ADC0_Input_To_Read(ADC0_Resistance_Hi_Gain_Channel_Select);
}


/***********************************************************************/
/* Measured DUT Voltage Low Gain - pull in single meas                 */
/***********************************************************************/
float ADC0_Low_Gain_Quick() {
float Accum;
    
    if (bufferB_Full == true){
        Accum = (float)adcResultBuffer[0][1][0];
        Accum = Accum * LTestData.ADC_Full_Scale_V;
        Accum = Accum / ADC_MAX_COUNT;
        bufferB_Full = false;
        adcSampleCntBuffer[0][1] = 0;
    }
    else if (bufferA_Full == true){
        Accum = (float)adcResultBuffer[0][0][0];
        Accum = Accum * LTestData.ADC_Full_Scale_V;
        Accum = Accum / ADC_MAX_COUNT;
        bufferA_Full = false;
        adcSampleCntBuffer[0][0] = 0;
    }
        else {
            Accum = ERROR_Volts;                    
        }

return (Accum);
}


/***********************************************************************/
/* Measured DUT Voltage Low Gain                                       */
/***********************************************************************/
float ADC0_Low_Gain() {
float Accum = 0;
int loop;

    /* hang around for 4 buffers */
    ADC0_Wait_1_Buffer;
    bufferA_Full = false;
    bufferB_Full = false;

    while ((bufferA_Full == false) && (bufferB_Full == false)) {};
    
    if (bufferB_Full == true){
        for(loop=0; loop < adcSampleCntBuffer[0][1]; loop++)
            Accum += (float)adcResultBuffer[0][1][loop];
        if (adcSampleCntBuffer[0][1] != 0){
            Accum = Accum / adcSampleCntBuffer[0][1];
            Accum = Accum * LTestData.ADC_Full_Scale_V;
            Accum = Accum / ADC_MAX_COUNT;
        }
        else {
            Accum = ERROR_Volts;        
        }
        bufferB_Full = false;
        adcSampleCntBuffer[0][1] = 0;
    }
    else if (bufferA_Full == true){
        for(loop=0; loop < adcSampleCntBuffer[0][0]; loop++)
            Accum += (float)adcResultBuffer[0][0][loop];
        if (adcSampleCntBuffer[0][0] != 0) {
            Accum = Accum / adcSampleCntBuffer[0][0];
            Accum = Accum * LTestData.ADC_Full_Scale_V;
            Accum = Accum / ADC_MAX_COUNT;
        }
        else {
            Accum = ERROR_Volts;                    
        }
        bufferA_Full = false;
        adcSampleCntBuffer[0][0] = 0;
    }
    else
        Accum = ERROR_Volts;

    return (Accum);
}


/***********************************************************************/
/* Measured DUT Voltage Low Gain immediately                           */
/***********************************************************************/
float ADC0_Low_Gain_Fast() {
float Accum = 0;


    Accum = ADCDATA0;
    Accum = Accum * LTestData.ADC_Full_Scale_V;
    Accum = Accum / ADC_MAX_COUNT;
    return (Accum);
}

/***********************************************************************/
/* Measured DUT Voltage High Gain immediately                           */
/***********************************************************************/
float ADC0_High_Gain_Fast() {
float Accum = 0;

    Accum = ADCDATA0;
    Accum = Accum * LTestData.ADC_Full_Scale_V;
    Accum = Accum / (ADC_MAX_COUNT * INA281_Gain);
    return (Accum);
}


/***********************************************************************/
/* Measured DUT Voltage High Gain                                       */
/***********************************************************************/
float ADC0_High_Gain() {
float Accum = 0;
int loop;

    /* hang around for 4 buffers */
    ADC0_Wait_1_Buffer;
    bufferA_Full = false;
    bufferB_Full = false;

    while ((bufferA_Full == false) && (bufferB_Full == false)) {};

    if (bufferB_Full == true){
        for(loop=0; loop < adcSampleCntBuffer[0][1]; loop++)
            Accum += (float)adcResultBuffer[0][1][loop];
        if (adcSampleCntBuffer[0][1] != 0){
            Accum = Accum / adcSampleCntBuffer[0][1];
            Accum = Accum * LTestData.ADC_Full_Scale_V;
            Accum = Accum / (ADC_MAX_COUNT * INA281_Gain);
        }
        else {
            Accum = ERROR_Volts;        
        }
        bufferB_Full = false;
        adcSampleCntBuffer[0][1] = 0;
    }
    else if (bufferA_Full == true){
        for(loop=0; loop < adcSampleCntBuffer[0][0]; loop++)
            Accum += (float)adcResultBuffer[0][0][loop];
        if (adcSampleCntBuffer[0][0] != 0) {
            Accum = Accum / adcSampleCntBuffer[0][0];
            Accum = Accum * LTestData.ADC_Full_Scale_V;
            Accum = Accum / (ADC_MAX_COUNT * INA281_Gain);
        }
        else {
            Accum = ERROR_Volts;                    
        }
        bufferA_Full = false;
        adcSampleCntBuffer[0][0] = 0;
    }
    else
        Accum = ERROR_Volts;

    return (Accum);
}

/***********************************************************************/
/* Measured Current Sense Voltage Quick Look                                      */
/***********************************************************************/
float Current_Sense_Voltage_Quick() {
float Accum = 0;

    if (bufferB_Full == true){
        Accum = (float)adcResultBuffer[1][1][0];
        Accum = Accum * LTestData.ADC_Full_Scale_V;
        Accum = Accum / (ADC_MAX_COUNT * INA281_Gain);
        bufferB_Full = 0;
        adcSampleCntBuffer[1][1] = 0;
    }
    else if (bufferA_Full == true){
        Accum = (float)adcResultBuffer[1][0][0];
        Accum = Accum * LTestData.ADC_Full_Scale_V;
        Accum = Accum / (ADC_MAX_COUNT * INA281_Gain);
        bufferA_Full = false;
        adcSampleCntBuffer[1][0] = 0;
    }
    else
        Accum = ERROR_Volts;

    return (Accum);
}




/***********************************************************************/
/* Measured Current Sense Voltage                                      */
/***********************************************************************/
float Current_Sense_Voltage() {
float Accum = 0;
int loop;

    if (bufferB_Full == true){
        for(loop=0; loop < adcSampleCntBuffer[1][1]; loop++)
            Accum += (float)adcResultBuffer[1][1][loop];
        if (adcSampleCntBuffer[1][1] != 0){
            Accum = Accum / adcSampleCntBuffer[1][1];
            Accum = Accum * LTestData.ADC_Full_Scale_V;
            Accum = Accum / (ADC_MAX_COUNT * INA281_Gain);
        }
        else {
            Accum = ERROR_Volts;        
        }
        bufferB_Full = false;
        adcSampleCntBuffer[1][1] = 0;
    }
    else if (bufferA_Full == true){
        for(loop=0; loop < adcSampleCntBuffer[1][0]; loop++)
            Accum += (float)adcResultBuffer[1][0][loop];
        if (adcSampleCntBuffer[1][0] != 0) {
            Accum = Accum / adcSampleCntBuffer[1][0];
            Accum = Accum * LTestData.ADC_Full_Scale_V;
            Accum = Accum / (ADC_MAX_COUNT * INA281_Gain);
        }
        else {
            Accum = ERROR_Volts;                    
        }
        bufferA_Full = false;
        adcSampleCntBuffer[1][0] = 0;
    }
    else
        Accum = ERROR_Volts;

    return (Accum);
}



/***********************************************************************/
/* Enable ADC0                                                         */
/***********************************************************************/
void Enable_ADC_0() {
    
    ADCCON3bits.DIGEN0 = 1; // Enable ADC0
}

/***********************************************************************/
/* Disable ADC0                                                         */
/***********************************************************************/
void Disable_ADC_0() {
    
    ADCCON3bits.DIGEN0 = 0; // Disable ADC0

}

/***********************************************************************/
/* Enable ADC1                                                         */
/***********************************************************************/
void Enable_ADC_1() {
    
    ADCCON3bits.DIGEN1 = 1; // Enable ADC1
}

/***********************************************************************/
/* Disable ADC1                                                         */
/***********************************************************************/
void Disable_ADC_1() {
    
    ADCCON3bits.DIGEN1 = 0; // Disable ADC1

}



/***********************************************************************/
/* Measure High Resistance                                             */
/*      Set Test Current to 10mA                                       */
/*      Set ADC to measure DUT at low gain                             */
/*      Measure voltage integrating over a buffer                      */
/*  Return resistance in Ohms   = MEasured voltage/test current        */
/*                                                                     */
/*  Maximum resistance on this range will be                           */
/*      3.1 = 0.01 *R                                                  */
/*      R = 310 Ohms odd                                               */
/***********************************************************************/
float Measure_High_Resistance() {
    float Measured_Working, Measured_Voltage;
    
    Set_Test_Current(Test_Current_High_Range);   /* 10mA */
    Resistance_Settle;
    Measure_DUT_Voltage_Low_Gain(); /* selects low gain DUT measurement channel */
    Resistance_Post_Meas_Settle;
    Measured_Voltage = ADC0_Low_Gain();
   /* I am here for test */
    LTestData.Scratch = Measured_Voltage;
    /* should probably put some form of trap[ in here for overscale */
    Measured_Working = Measured_Voltage/LTestData.ISet_CAL_10mA;
    /* switch test current off */
    Clear_Test_Current();
    
   return (Measured_Working);
}

/***********************************************************************/
/* Measure High Resistance shortly after applying current              */
/*      Set Test Current to 10mA                                       */
/*      Set ADC to measure DUT at low gain                             */
/*      Measure voltage on single sample                               */
/*  Return resistance in Ohms   = MEasured voltage/test current        */
/*                                                                     */
/*  Maximum resistance on this range will be                           */
/*      3.1 = 0.01 *R                                                  */
/*      R = 310 Ohms odd                                               */
/***********************************************************************/
float Measure_High_Resistance_Fast() {
    float Measured_Working, Measured_Voltage;
    
    /* we want to make sure everything is cleared out and discharged for this test*/
    Clear_Test_Current();
    Short_DUT();  // we want the DUT shorted and the current source to stabilise
    Set_Test_Current(Test_Current_High_Range);   /* 10mA */
    Resistance_Fast_Settle;
    Measure_DUT_Voltage_Low_Gain(); /* selects low gain DUT measurement channel */
    Resistance_Fast_Post_Meas_Channel_Sel_Settle;
    Un_Short_DUT();  // Remove the short across the DUT then measure
    Restsiance_Fast_Delay_To_Meas;
    Measured_Voltage = ADC0_Low_Gain_Fast();
   /* I am here for test */
    LTestData.Scratch = Measured_Voltage;
    /* should probably put some form of trap[ in here for overscale */
    Measured_Working = Measured_Voltage/LTestData.ISet_CAL_10mA;
    /* switch test current off */
    Clear_Test_Current();
    
   return (Measured_Working);
}


/***********************************************************************/
/* Measure Medium Resistance                                           */
/*      Set Test Current to 100mA                                      */
/*      Set ADC to measure DUT at low gain                             */
/*      MEasure voltage                                                */
/*  Return resistance in Ohms   = MEasured voltage/test current        */
/*                                                                     */
/*  Maximum resistance on this range will be                           */
/*      3.1 = 0.1 *R                                                   */
/*      R = 30 Ohms odd                                                */
/*      R = 30 miliohms min                                            */
/***********************************************************************/
float Measure_Medium_Resistance() {
    float Measured_Working, Measured_Voltage;
    
    Set_Test_Current(Test_Current_Medium_Range);   /* 100mA */
    Resistance_Settle;
    Measure_DUT_Voltage_Low_Gain(); /* selects low gain DUT measurement channel */
    Resistance_Post_Meas_Settle;
    Measured_Voltage = ADC0_Low_Gain();
   /* I am here for test */
    LTestData.Scratch = Measured_Voltage;
    /* should probably put some form of trap[ in here for overscale */
    Measured_Working = Measured_Voltage/LTestData.ISet_CAL_100mA;
    Clear_Test_Current();

    return (Measured_Working);
}

/***********************************************************************/
/* Measure Medium Resistance shortly after applying test current       */
/*      Set Test Current to 100mA                                      */
/*      Set ADC to measure DUT at low gain                             */
/*      MEasure voltage immediately                                    */
/*  Return resistance in Ohms   = MEasured voltage/test current        */
/*                                                                     */
/*  Maximum resistance on this range will be                           */
/*      3.1 = 0.1 *R                                                   */
/*      R = 30 Ohms odd                                                */
/*      R = 30 miliohms min                                            */
/***********************************************************************/
float Measure_Medium_Resistance_Fast() {
    float Measured_Working, Measured_Voltage;
    
    /* we want to make sure everything is cleared out and discharged for this test*/
    Clear_Test_Current();
    Short_DUT();  // we want the DUT shorted and the current source to stabilise
    Set_Test_Current(Test_Current_Medium_Range);   /* 100mA */
    Resistance_Fast_Settle;
    Measure_DUT_Voltage_Low_Gain(); /* selects low gain DUT measurement channel */
    Resistance_Fast_Post_Meas_Channel_Sel_Settle;
    Un_Short_DUT();  // Remove the short across the DUT then measure
    Restsiance_Fast_Delay_To_Meas;
    Measured_Voltage = ADC0_Low_Gain_Fast();
   /* I am here for test */
    LTestData.Scratch = Measured_Voltage;
    /* should probably put some form of trap[ in here for overscale */
    Measured_Working = Measured_Voltage/LTestData.ISet_CAL_100mA;
    Clear_Test_Current();

    return (Measured_Working);
}


/***********************************************************************/
/* Measure MedLow Resistance                                           */
/*      Set Test Current to 10mA                                       */
/*      Set ADC to measure DUT at high gain                            */
/*      MEasure voltage                                                */
/*  Return resistance in Ohms   = MEasured voltage/test current        */
/*                                                                     */
/*  Maximum resistance on this range will be                           */
/*      3.1 = 0.01 *R * 20                                             */
/*      R = 15 Ohms max odd                                            */
/*      R = 3 miliohms min odd  (optimistic)                           */
/***********************************************************************/
float Measure_MedLow_Resistance() {
    float Measured_Working, Measured_Voltage;
    
    Set_Test_Current(Test_Current_High_Range);   /* 10mA */
    Resistance_Settle;
    Measure_DUT_Voltage_High_Gain(); /* selects high gain DUT measurement channel */
    Resistance_Post_Meas_Settle;
    Measured_Voltage = ADC0_High_Gain();
    /* I am here for test */
    LTestData.Scratch = Measured_Voltage;
    /* should probably put some form of trap in here for overscale */
    Measured_Working = Measured_Voltage/LTestData.ISet_CAL_10mA;
    Clear_Test_Current();
    
    return (Measured_Working);
}


/***********************************************************************/
/* Measure MedLow Resistance shortly after applying test current       */
/*      Set Test Current to 10mA                                       */
/*      Set ADC to measure DUT at high gain                            */
/*      MEasure voltage on first sample                                */
/*  Return resistance in Ohms   = MEasured voltage/test current        */
/*                                                                     */
/*  Maximum resistance on this range will be                           */
/*      3.1 = 0.01 *R * 20                                             */
/*      R = 15 Ohms max odd                                            */
/*      R = 3 miliohms min odd  (optimistic)                           */
/***********************************************************************/
float Measure_MedLow_Resistance_Fast() {
    float Measured_Working, Measured_Voltage;
    
    /* we want to make sure everything is cleared out and discharged for this test*/
    Clear_Test_Current();
    Short_DUT();  // we want the DUT shorted and the current source to stabilise
    Set_Test_Current(Test_Current_High_Range);   /* 10mA */
    Resistance_Fast_Settle;
    Measure_DUT_Voltage_High_Gain(); /* selects high gain DUT measurement channel */
    Resistance_Fast_Post_Meas_Channel_Sel_Settle;
    Un_Short_DUT();  // Remove the short across the DUT then measure
    Restsiance_Fast_Delay_To_Meas;
    Measured_Voltage = ADC0_High_Gain_Fast();
    /* I am here for test */
    LTestData.Scratch = Measured_Voltage;
    /* should probably put some form of trap in here for overscale */
    Measured_Working = Measured_Voltage/LTestData.ISet_CAL_10mA;
    Clear_Test_Current();
    
    return (Measured_Working);
}


/***********************************************************************/
/* Measure Low Resistance                                              */
/*      Set Test Current to 100mA                                      */
/*      Set ADC to measure DUT at high gain                            */
/*      MEasure voltage                                                */
/*  Return resistance in Ohms   = MEasured voltage/test current        */
/*                                                                     */
/*  Maximum resistance on this range will be                           */
/*      3.1 = 0.1 *R * 20                                              */
/*      R = 1.5 Ohms max odd                                           */
/*      R = 3 miliohms min odd  (optimistic)                           */
/***********************************************************************/
float Measure_Low_Resistance() {
    float Measured_Working, Measured_Voltage;
    
    Set_Test_Current(Test_Current_Medium_Range);   /* 100mA */
    Resistance_Settle;
    Measure_DUT_Voltage_High_Gain(); /* selects high gain DUT measurement channel */
    Resistance_Post_Meas_Settle;
    Measured_Voltage = ADC0_High_Gain();
    /* I am here for test */
    LTestData.Scratch = Measured_Voltage;
    /* should probably put some form of trap in here for overscale */
    Measured_Working = Measured_Voltage/LTestData.ISet_CAL_100mA;
    Clear_Test_Current();
    
    return (Measured_Working);
}


/***********************************************************************/
/* Measure Low Resistance shortly after setting current                */
/*      Set Test Current to 100mA                                      */
/*      Set ADC to measure DUT at high gain                            */
/*      MEasure voltage                                                */
/*  Return resistance in Ohms   = MEasured voltage/test current        */
/*                                                                     */
/*  Maximum resistance on this range will be                           */
/*      3.1 = 0.1 *R * 20                                              */
/*      R = 1.5 Ohms max odd                                           */
/*      R = 3 miliohms min odd  (optimistic)                           */
/***********************************************************************/
float Measure_Low_Resistance_Fast() {
    float Measured_Working, Measured_Voltage;
    
    /* we want to make sure everything is cleared out and discharged for this test*/
    Clear_Test_Current();
    Short_DUT();  // we want the DUT shorted and the current source to stabilise
    Set_Test_Current(Test_Current_Medium_Range);   /* 100mA */
    Resistance_Fast_Settle;
    Measure_DUT_Voltage_High_Gain(); /* selects high gain DUT measurement channel */
    Resistance_Fast_Post_Meas_Channel_Sel_Settle;
    Un_Short_DUT();  // Remove the short across the DUT then measure
    Restsiance_Fast_Delay_To_Meas;
    Measured_Voltage = ADC0_High_Gain_Fast();
    /* I am here for test */
    LTestData.Scratch = Measured_Voltage;
    /* should probably put some form of trap in here for overscale */
    Measured_Working = Measured_Voltage/LTestData.ISet_CAL_100mA;
    Clear_Test_Current();
    
    return (Measured_Working);
}


/***********************************************************************/
/* Measure Low Low Resistance                                          */
/*      Set Test Current to 1A                                         */
/*      Set ADC to measure DUT at high gain                            */
/*      MEasure voltage                                                */
/*  Return resistance in Ohms   = MEasured voltage/test current        */
/*                                                                     */
/*  Maximum resistance on this range will be                           */
/*      3.1 = 1 *20*R                                                  */
/*      R = 0.15 Ohms max odd                                          */
/*      R = 0.1 miliohms min odd  (optimistic)                         */
/***********************************************************************/
float Measure_LowLow_Resistance() {
    float Measured_Working, Measured_Voltage;
    
    Set_Test_Current(Test_Current_Low_Range);   /* 1A */
    Resistance_Settle;
    Measure_DUT_Voltage_High_Gain(); /* selects high gain DUT measurement channel */
    Resistance_Post_Meas_Settle;
    Measured_Voltage = ADC0_High_Gain();
   /* I am here for test */
    LTestData.Scratch = Measured_Voltage;
    /* should probably put some form of trap[ in here for overscale */
    Measured_Working = Measured_Voltage/LTestData.ISet_CAL_1A;
    
    Measured_Voltage = Measured_Working;
    Measured_Voltage = ADC0_High_Gain();
    Clear_Test_Current();
    
//    return (Measured_Voltage);
    return (Measured_Working);
}


/***********************************************************************/
/* Measure Low Low Resistance shortly after setting the current        */
/*      Set Test Current to 1A                                         */
/*      Set ADC to measure DUT at high gain                            */
/*      MEasure voltage                                                */
/*  Return resistance in Ohms   = MEasured voltage/test current        */
/*                                                                     */
/*  Maximum resistance on this range will be                           */
/*      3.1 = 1 *20*R                                                  */
/*      R = 0.15 Ohms max odd                                          */
/*      R = 0.1 miliohms min odd  (optimistic)                         */
/***********************************************************************/
float Measure_LowLow_Resistance_Fast() {
    float Measured_Working, Measured_Voltage;
   
    /* we want to make sure everything is cleared out and discharged for this test*/
    Clear_Test_Current();
    /* Discharge the DUT to be sure, then set the Test current to 10mA*/
    Short_DUT();  // Remove the short across the DUT then measure
    Set_Test_Current(Test_Current_Low_Range);   /* 1A */
    Resistance_Fast_Settle;
    Measure_DUT_Voltage_High_Gain(); /* selects high gain DUT measurement channel */
    Resistance_Fast_Post_Meas_Channel_Sel_Settle;

    // TEST CODE DEWLETE
    FF_D_Set();
    CORETIMER_DelayUs(1);
    FF_D_Clear();

    Un_Short_DUT();  // Remove the short across the DUT then measure
    Restsiance_Fast_Delay_To_Meas;
    Measured_Voltage = ADC0_High_Gain_Fast();

    // TEST CODE DEWLETE
    FF_D_Set();
    CORETIMER_DelayUs(1);
    FF_D_Clear();

    
    /* I am here for test */
    LTestData.Scratch = Measured_Voltage;
    /* should probably put some form of trap[ in here for overscale */
    Measured_Working = Measured_Voltage/LTestData.ISet_CAL_1A;
    
    Measured_Voltage = Measured_Working;
    Measured_Voltage = ADC0_High_Gain();
    Clear_Test_Current();
    
//    return (Measured_Voltage);
    return (Measured_Working);
}

/***********************************************************************/
/* Set Timer 3 to sample rate requirted for ADC                        */
/***********************************************************************/
void ADC_Sample_Rate(long int Sample_Rate)
{
    TMR3_Stop();
    TMR3_Initialize();
    TMR3_PeriodSet((long int) (((float)CORE_TIMER_FREQUENCY * 2.0/ (float)Sample_Rate)-2));    
    TMR3_Start();
}


/***********************************************************************/
/* Grab Sample Buffer for Capacitance Measurement                      */
/***********************************************************************/
void ADC_Cap_Buffer_Capture(long int Sample_Rate, float Test_Current, int *Sample_Cnt , bool* Overflow)
{
//    uint16_t *BufA_Ptr = &adcResultBuffer[0][0][0];
//    uint16_t *BufB_Ptr = &adcResultBuffer[0][1][0];
//    uint16_t *BufA_Ptr_Rst = &adcResultBuffer[0][0][0];
//    uint16_t *BufB_Ptr_Rst = &adcResultBuffer[0][1][0];    
//    int Meas_Ptr_Cntr, Precharge_Counter, Meas_Buffer_Full ;
//    int Meas_Ptr_Cntr, Meas_Buffer_Full ;

    long int Free_Time, FT1;
//    bool Threshold_Found, Final_Samples = false;

    Set_Test_Current(Test_Current);
    ADC_Sample_Rate(Sample_Rate);
    
//    ADCHS_ModulesDisable ( ADCHS_MODULE1_MASK);    //Stops channel 1
//    ADCHS_ModulesEnable ( ADCHS_MODULE0_MASK | ADCHS_MODULE1_MASK);    //Stops channel 1
    ADCDSTATbits.DMACEN = 0;    // reset DMA
    ADCDSTATbits.DMAEN = 0;
//    ADCDSTATbits.RAFIEN0 = 0;
//    ADCDSTATbits.RBFIEN0 = 0;
//    ADCDSTATbits.RAFIEN1 = 1;
//    ADCDSTATbits.RBFIEN1 = 1;

//    Discharge_DUT();   // ensure DUT is discharged
    Short_DUT();
    /* hang around for a good while with Interrupts disabled */
    IEC3bits.AD1FCBTIE = 0;
    Capacitance_Settle;
    *Sample_Cnt = 0;            // This is the count of samples we are putting into our Memory Array 
    Free_Time = 0;
    FT1 = 0;
//    Precharge_Counter = 0;      // This counter checks that we are not sitting waiting for a DUT for ever
//    BufA_Ptr = BufA_Ptr_Rst;    // Pointer to the start of DMA ping pong buffer A - quicker  this way
//    BufB_Ptr = BufB_Ptr_Rst;    // Pointer to the start of DMA ping pong buffer B - quicker this way
      Meas_Buffer_Full = false;     // start looking to measure data as thats what we are here for
      Meas_Ptr = Meas_Ptr_Rst;                    /* point Meas_Ptr to the result data structure */
//    ADCDSTATbits.DMACEN = 1;    // turn DMA on
//    ADCDSTATbits.DMAEN = 1;
    /* delay about two buffers */
//    IFS3bits.AD1FCBTIF = 0;
//    CORETIMER_DelayUs((int)((2*1000000*Buffer_Size)/Sample_Rate));
//    IFS3bits.AD1FCBTIF = 0;
//    IFS3bits.AD1FCBTIF = 1;
    *Overflow = false;
    Un_Short_DUT();
//    Threshold_Found = false;        // use this to stop copying once we find the threshold
//    Final_Samples = true;           // The final samples will usually be in an incomplete DMA buffer
  



//    IEC3bits.AD1FCBTIE = 0; // Disable DMA Buffer full interrupt
//    IEC3bits.AD1FCBTIE = 1; // Disable DMA Buffer full interrupt

            FT1 = _CP0_GET_COUNT();
//    IFS3bits.AD1FCBTIF = 0;
//        ADCDSTATbits.DMACEN = 1;    // turn DMA on
    ADCDSTATbits.DMAEN = 1;         // turn DMA on
            
    bufferA_Full = false;       // Used by the DMA engine
    bufferB_Full = false;       // Used by the DMA engine
    IEC3bits.AD1FCBTIE = 1;     // enable interrupts



    // remove the short from the DUT
    while (!Meas_Buffer_Full)    //  GRab the full buffer
    {
        // we wait politely
    }
        IEC3bits.AD1FCBTIE = 0;     // disenable interrupts

            Free_Time = (_CP0_GET_COUNT() - FT1);

                *Sample_Cnt = (int)Free_Time;
//    time_cnt1 = _CP0_GET_COUNT();  
    // turn the current off 
//    Clear_Test_Current();
//                    IFS3bits.AD1FCBTIF = 1;
    
    
                adcSampleCntBuffer[0][0]=0;
                adcSampleCntBuffer[1][0]=0;

 
    
    
    
    
    
    




    
    
    
    
    
    
    
    
    
    
/*    
    
    // remove the short from the DUT
    while (!Meas_Buffer_Full)    //  GRab the full buffer
    {
        Meas_Ptr_Cntr = Buffer_Size;
        if (bufferA_Full) {
            FF_D_Clear();  

            while (Meas_Ptr_Cntr){
                *Meas_Ptr++ = *BufA_Ptr++;
                Meas_Ptr_Cntr--;
            }
            bufferA_Full = false;
            BufA_Ptr = BufA_Ptr_Rst;
            *Sample_Cnt += Buffer_Size;
            FF_D_Set();
//    IFS3bits.AD1FCBTIF = 1;

        }
        if (bufferB_Full) {
            FF_CLK_Clear();  
           while (Meas_Ptr_Cntr){
                *Meas_Ptr++ = *BufB_Ptr++;
                Meas_Ptr_Cntr--;
            }
            bufferB_Full = false;
            BufB_Ptr = BufB_Ptr_Rst;
            *Sample_Cnt += Buffer_Size;
                        FF_CLK_Set();
//    IFS3bits.AD1FCBTIF = 1;
        }
        if ((*Sample_Cnt) > (Meas_Buffer_Size-1)){
            Meas_Buffer_Full = true;
        }
     }
            Free_Time = (_CP0_GET_COUNT() - FT1);

                *Sample_Cnt = (int)Free_Time;
//    time_cnt1 = _CP0_GET_COUNT();  
    // turn the current off 
//    Clear_Test_Current();
//                    IFS3bits.AD1FCBTIF = 1;
*/
/*    
    
                adcSampleCntBuffer[0][0]=0;
                adcSampleCntBuffer[1][0]=0;

 */
                
}



/***********************************************************************/
/* Grab Sample Buffer for Capacitance Measurement                      */
/***********************************************************************/
void ADC_Cap_Buffer_Capture_2024_10_03(long int Sample_Rate, float Test_Current, uint16_t *Meas_Ptr, int *Sample_Cnt , bool* Overflow)
{
    uint16_t *BufA_Ptr = &adcResultBuffer[0][0][0];
    uint16_t *BufB_Ptr = &adcResultBuffer[0][1][0];
    uint16_t *BufA_Ptr_Rst = &adcResultBuffer[0][0][0];
    uint16_t *BufB_Ptr_Rst = &adcResultBuffer[0][1][0];    
    int Meas_Ptr_Cntr, Precharge_Counter ;
    bool Threshold_Found, Final_Samples = false;
        

    Set_Test_Current(Test_Current);
    ADC_Sample_Rate(Sample_Rate);
    
//    ADCHS_ModulesDisable ( ADCHS_MODULE1_MASK);    //Stops channel 1
//    ADCHS_ModulesEnable ( ADCHS_MODULE0_MASK | ADCHS_MODULE1_MASK);    //Stops channel 1
    ADCDSTATbits.DMACEN = 0;    // reset DMA
    ADCDSTATbits.DMAEN = 0;
//    ADCDSTATbits.RAFIEN0 = 0;
//    ADCDSTATbits.RBFIEN0 = 0;
//    ADCDSTATbits.RAFIEN1 = 1;
//    ADCDSTATbits.RBFIEN1 = 1;
//    IFS3bits.AD1FCBTIF = 0;
            
//    IFS3bits.AD1FCBTIF = 1;


    Discharge_DUT();   // ensure DUT is discharged
    Short_DUT();
    /* hang around for a good while */
    Capacitance_Settle;
    Un_Short_DUT();
    bufferA_Full = false;       // Used by the DMA engine
    bufferB_Full = false;       // Used by the DMA engine
    *Sample_Cnt = 0;            // This is the count of samples we are putting into our Memory Array 
    Precharge_Counter = 0;      // This counter checks that we are not sitting waiting for a DUT for ever
    BufA_Ptr = BufA_Ptr_Rst;    // Pointer to the start of DMA ping pong buffer A - quicker  this way
    BufB_Ptr = BufB_Ptr_Rst;    // Pointer to the start of DMA ping pong buffer B - quicker this way
    Meas_Ptr_Cntr = Buffer_Size;    // counter to use in copying from DMA buffer to data array
    Threshold_Found = false;        // use this to stop copying once we find the threshold
    Final_Samples = true;           // The final samples will usually be in an incomplete DMA buffer
    Meas_Ptr = &LTestData.Meas_Buffer[0];
    ADCDSTATbits.DMACEN = 1;    // turn DMA on
    ADCDSTATbits.DMAEN = 1;
    *Overflow = false;
    while ((!Threshold_Found) || (Final_Samples))    //    while ((float)ADCDATA0 < Cap_Meas_Voltage_ADC_Val)
    {
        Meas_Ptr_Cntr = Buffer_Size;
        if (bufferA_Full) {
            if (Threshold_Found) Final_Samples = false;
            while (Meas_Ptr_Cntr){
                *Meas_Ptr++ = *BufA_Ptr++;
//                Meas_Ptr++;
//                BufA_Ptr++;
                Meas_Ptr_Cntr--;
                (*Sample_Cnt)++;
            }
            bufferA_Full = false;
            BufA_Ptr = BufA_Ptr_Rst;
        }
        else if (bufferB_Full) {
            if (Threshold_Found) Final_Samples = false;
            while (Meas_Ptr_Cntr){
                *Meas_Ptr++ = *BufB_Ptr++;
//                Meas_Ptr++;
//                BufB_Ptr++;
                Meas_Ptr_Cntr--;
                (*Sample_Cnt)++;
            }
            bufferB_Full = false;
            BufB_Ptr = BufB_Ptr_Rst;
         }
        Precharge_Counter++;            // increment this - this only matters during initial charge
        if (ADCDATA0 > Cap_Meas_Voltage_ADC_Val) {
            Threshold_Found = true;
        }
        else if ((*Sample_Cnt) > Meas_Buffer_Size){
            Threshold_Found = true;   // stop capturing data
            *Overflow = true; 
        }
        else if (Precharge_Counter > Precharge_Counter_Overflow) {
            Threshold_Found = true;    // start the ADC sampling - let the following processing pull the error out            
        }
     }
//    time_cnt1 = _CP0_GET_COUNT();  
    /* turn the current off */
//    Clear_Test_Current();
}



void ADC_Cap_Buffer_Find_Thresholds(uint16_t *Meas_Ptr, int* First_Sample_Meas, int* Final_Sample_Meas)
{
    bool First_Sample_Found, Final_Sample_Found = false;

    //First_Sample_Meas, Final_Sample_Meas    
    First_Sample_Found = false;   // Start searching
    Final_Sample_Found = false;   // Start searching
    (*Final_Sample_Meas) = 0; // set this to zero and use as flag
    (*First_Sample_Meas) = 0; // set this to zero and use as flag
    Meas_Ptr = &LTestData.Meas_Buffer[0];
    while (!First_Sample_Found) {
        if ((*Meas_Ptr) < Cap_Meas_Min_Threshold) {
            Meas_Ptr++;
            (*First_Sample_Meas)++;
            if ((*First_Sample_Meas) > Meas_Buffer_Size){
                First_Sample_Found = true;
                Final_Sample_Found = true;              // dont go looking for final sample 
                (*First_Sample_Meas) = Meas_Buffer_Size;   // lets call this an error
                (*Final_Sample_Meas) = Meas_Buffer_Size;   // lets call this an error
            }
        }
        else{
            First_Sample_Found = true;
        }
            
    } // First Sample_Meas now points to the first sample > threshold OR end of buffer
    
    /* start with final sample = first sample position */
    (*Final_Sample_Meas) = (*First_Sample_Meas);
    while (!Final_Sample_Found) {
        if ((*Meas_Ptr) < Cap_Meas_Voltage_ADC_Val) {
            Meas_Ptr++;
            (*Final_Sample_Meas)++;
            if ((*Final_Sample_Meas) > Meas_Buffer_Size){
                (*Final_Sample_Meas) = Meas_Buffer_Size;   // lets call this an error
                Final_Sample_Found = true;
            }
        }
        else {
            Final_Sample_Found = true;
        }
    } // Final Sample_Meas now points to the first sample > threshold OR end of buffer
}




/************************************************************************/
/* Grab Sample Buffer for Capacitance Measurement                       */
/*  This assumes the current sourse is set and running                  */
/************************************************************************/
void ADC_Ind_Buffer_Capture(long int Sample_Rate, uint16_t *Meas_Ptr)
{
    uint16_t *BufA_Ptr = &adcResultBuffer[0][0][0];
    uint16_t *BufB_Ptr = &adcResultBuffer[0][1][0];
    uint16_t *BufA_Ptr_Rst = &adcResultBuffer[0][0][0];
    uint16_t *BufB_Ptr_Rst = &adcResultBuffer[0][1][0];    
    int Meas_Ptr_Cntr, Buffers;
        

    ADC_Sample_Rate(Sample_Rate);
    ADCHS_ModulesDisable ( ADCHS_MODULE1_MASK);    //Stops channel 1
    ADCDSTATbits.DMACEN = 0;    // reset DMA
    ADCDSTATbits.DMAEN = 0;

//    Discharge_DUT();   // ensure DUT is discharged
    Short_DUT();
    /* hang around for 4 buffers */
    ADC0_Wait_1_Buffer;
    bufferA_Full = false;       // Used by the DMA engine
    bufferB_Full = false;       // Used by the DMA engine
    BufA_Ptr = BufA_Ptr_Rst;    // Pointer to the start of DMA ping pong buffer A - quicker  this way
    BufB_Ptr = BufB_Ptr_Rst;    // Pointer to the start of DMA ping pong buffer B - quicker this way
    Meas_Ptr_Cntr = Buffer_Size;    // counter to use in copying from DMA buffer to data array
    Meas_Ptr = &LTestData.Meas_Buffer[0];
    ADCDSTATbits.DMACEN = 1;    // turn DMa on
    ADCDSTATbits.DMAEN = 1;
    Buffers = 100;

    FF_D_Set();
    CORETIMER_DelayUs(5);
    FF_D_Clear(); 

    Un_Short_DUT();             // We have plenty of time before the fet switches off
    for (Buffers = 0; Buffers < 100; Buffers++)
    {
        Meas_Ptr_Cntr = Buffer_Size;
        if (bufferA_Full) {
            while (Meas_Ptr_Cntr){
                *Meas_Ptr = *BufA_Ptr;
                Meas_Ptr++;
                BufA_Ptr++;
                Meas_Ptr_Cntr--;
            }
            bufferA_Full = false;
            BufA_Ptr = BufA_Ptr_Rst;
        }
        else if (bufferB_Full) {
            while (Meas_Ptr_Cntr){
                *Meas_Ptr = *BufB_Ptr;
                Meas_Ptr++;
                BufB_Ptr++;
                Meas_Ptr_Cntr--;
            }
            bufferB_Full = false;
            BufB_Ptr = BufB_Ptr_Rst;
         }
        while ((!bufferA_Full) && (!bufferB_Full))
        {};
     }
    
    FF_D_Set();
    CORETIMER_DelayUs(5);
    FF_D_Clear(); 


}
