/*******************************************************************************

 Digital Preamp State Machine and Control
 *
  Company:
    TGM.

  File Name:
    Digital_Preamp.c

  Summary:
    This file contains the core preamp functionality and state machine
 *
 * V0.2     - LCD working.
 *          - Main UI functioning menus channel and EQ
 *          - EEPROM load and save works
 * V0.4     - DSP clock and I/O to ADC and DACS running
 *          - Loading code - is going from PIC to ADAU
 *          - ISSUES:  No data out from ADAU (minor one!)
 * V0.5     - Sort out calibration to use measured values
 *******************************************************************************/

// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include <stddef.h>                     // Defines NULL
#include <stdbool.h>                    // Defines true
#include <stdlib.h>                     // Defines EXIT_FAILURE
#include <stdio.h>
#include "definitions.h"                // SYS function prototypes
#include "Inductor_Tester.h"
#include "Inductor_Tester_Meas.h"
#include "LCD_lib_busy.h"
#include "LCD_config.h"
#include <xc.h>
#include <sys/attribs.h>
#include "interrupts.h"
#include "definitions.h"
#include "EEPROM.h"
#include "MCP4822.h"
#include "sys/kmem.h"
//#include "peripheral/coretimer/plib_coretimer.h"
//#include "device.h"

/* This is where all the data is stored... */
/* defined as extern in Inductor_Tester.h */
Inductor_Tester_DATA LTestData;
int loop, test_temp;
__COHERENT uint16_t adcResultBuffer[2][2][Buffer_Size];
__COHERENT uint8_t adcSampleCntBuffer[2][2];    
volatile int bufferA_Full;
volatile int bufferB_Full;
float input_voltage;


/********************************************************/
/*   ISR for ADC                                        */
/********************************************************/
void ADC_ResultHandler(ADCHS_DMA_STATUS dmaStatus, uintptr_t context)
{
    if ((dmaStatus & ADCHS_DMA_STATUS_RAF0) || (dmaStatus & ADCHS_DMA_STATUS_RAF1))
    {
        bufferA_Full = true;
    }
    
    if ((dmaStatus & ADCHS_DMA_STATUS_RBF0) || (dmaStatus & ADCHS_DMA_STATUS_RBF1))
    {
        bufferB_Full = true;
    }    
}



/********************************************************/
/*  check inputs                                        */
/********************************************************/
int Key_Pressed()
{
    int Key_Sense = 0;
    
    /* load the answers into the structure Input goes LOW if pressed*/
    LTestData.Up_Key = Up_Get();
    LTestData.Down_Key = DOWN_Get();
    LTestData.Spare_GPIO_Key = SPARE_GPIO_Get();
    LTestData.Start_Key = START_Get();
            
    if (!LTestData.Up_Key || !LTestData.Down_Key  || !LTestData.Spare_GPIO_Key || !LTestData.Start_Key)
        Key_Sense = 1;
    else 
        Key_Sense = 0;
    
    return Key_Sense;
}

/********************************************************/
/*  clear inputs                                        */
/********************************************************/
int Clear_Key_Pressed()
{
    int Key_Sense = 0;
    
    /* load the answers into the structure Input goes LOW if pressed*/
    LTestData.Up_Key = Up_Get();
    LTestData.Down_Key = DOWN_Get();
    LTestData.Spare_GPIO_Key = SPARE_GPIO_Get();
    LTestData.Start_Key = START_Get();
            
    if (!LTestData.Up_Key || !LTestData.Down_Key  || !LTestData.Spare_GPIO_Key || !LTestData.Start_Key)
        Key_Sense = 1;
    else 
        Key_Sense = 0;
    
    return Key_Sense;
}




/************************************************************/
/*       LCD Init                                           */
/************************************************************/
void LCD_Boot(void)
{
    LCD_Start();
    LCD_Clear_Line1();
    LCD_Clear_Line2();
    LCD_TextOut(0,0,(unsigned char *)"TGM Says: V0.5  ");   // could be optimized
    LCD_TextOut(1,0,(unsigned char *)"LCD Booted OK   ");   // could be optimized
    CORETIMER_DelayMs(Splash_Time_ms);
}

/****************************************************************************/
/*  Splash Screen                                                           */
/****************************************************************************/
void LCD_Splash_Screen(void)
{
    LCD_TextOut(1,0,Splash_String_1);
    LCD_TextOut(0,0,Splash_String_0);
    CORETIMER_DelayMs(Splash_Time_ms);              // keep Splash screen 1s
    LCD_TextOut(1,0,Version_String);
    CORETIMER_DelayMs(Splash_Version_Time_ms);      // keep Splash screen 0.5s
    LTestData.UI_Update_Display = 1;  // flag display for update
}

/*******************************************************************************
  Function:
    void LTest_Initialize ( void )

  Remarks:
    See prototype in Inductor_Tester.h.
******************************************************************************/
void LTest_Initialize ( void )
{
    /* Place the App state machine in its initial state. */
    LTestData.state = Inductor_Tester_STATE_INIT;
    LTestData.heartbeatToggle = 1;
    LTestData.heartbeatCount = HeartbeatCountInit;
    LTestData.Revert_To_Idle_Counter = Revert_To_Idle;
    LTestData.UI_Update_Display = 0;
    LTestData.Up_Key = 0;
    LTestData.Down_Key = 0;
    LTestData.Spare_GPIO_Key = 0;
    LTestData.Start_Key = 0;
    LTestData.UI_Keypressed = 0;
    LTestData.TEMP_DATA = 0;              /* init scratch */
    LTestData.MemoryBankSelected = Default_Mem_Bank; /* initialise me */
    LTestData.Test_Current_Resistor = ((float)(Test_Resistor_Default)); /* an initial value - will upload from EEPROM */
    LTestData.Current_Meas_Resistor = ((float)(Measurement_Resistor_Default));  /* an initial value - will upload from EEPROM */
    LTestData.ISet_CAL_10mA = ((float)(DAC_ISet_10mA_Cal_Default)); /* set to default */
    LTestData.ISet_CAL_100mA = ((float)(DAC_ISet_100mA_Cal_Default)); /* set to default */
    LTestData.ISet_CAL_1A = ((float)(DAC_ISet_1A_Cal_Default)); /* set to default */
    LTestData.ICutoff_DAC_Zero_OP = ((float)(DAC_ICutoff_Zero_Default)); /* set to default */
    LTestData.ICutoff_DAC_1900mV_OP = ((float) (DAC_ICutoff_1900mV_Default)); /* set to default */
    LTestData.ADC_Full_Scale_V = ((float)(ADC_Full_Scale_V_Default)); /* set to default */
    LTestData.DAC_Full_Scale_V = DAC_Full_Scale_V_Default; /* set to default */
    LTestData.ICutoff_DAC_Cal = 1.0;  /* will update on loading real data */
    LTestData.DUT_Is_Capacitor = false;
    LTestData.DUT_Is_Resistor = false;
    LTestData.DUT_Is_Inductor = false;
    LTestData.Valid_DC_Resistance = false;
    LTestData.Valid_Capacitance = false;
    LTestData.Valid_Const_I_Ind = false;
    LTestData.Valid_Const_V_Ind = false;
    LTestData.Next_Range = false;
    LTestData.Cap_Cal_Low_Range = 0.0;
    LTestData.Teat_Rail_V_Meas = 0.0;
    
    
    /* update the DAC cal value in memory from this*/
    LTestData.ICutoff_DAC_Cal = DAC_ICutoff_1900mV_Default/LTestData.ICutoff_DAC_1900mV_OP;
}

/****************************************************************************/
/* Lets save relevant data to EEPROM                                      	*/
/****************************************************************************/
void Save_Data_To_Memory()
{
    /* temp_data */
    HDWordWriteSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + Temp_Data_Offset), LTestData.TEMP_DATA);
    /* test resistor_data - this value is stored in mcro ohms */
    HDWordWriteSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + Test_Resistor_Offset), ((int) (1000000 * LTestData.Test_Current_Resistor)));
    /* measurement resistor_data - this value is stored in micro ohms */
    HDWordWriteSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + Meas_Resistor_Offset), ((int) (1000000 * LTestData.Current_Meas_Resistor)));
    /* Zero DAC output test current - this value is stored in micro amps */
    HDWordWriteSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + DAC_ISet_CAL_10mA_Offset), ((int) (1000000 * LTestData.ISet_CAL_10mA)));
    /* ISet Calibration Factor at 100mA scaled by 1000000 */
    HDWordWriteSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + DAC_ISet_CAL_100mA_Offset), ((int) (1000000 * LTestData.ISet_CAL_100mA)));
    /* ISet Calibration Factor at 1A scaled by 1000000 */
    HDWordWriteSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + DAC_ISet_CAL_1A_Offset), ((int) (1000000 * LTestData.ISet_CAL_1A)));
    /* Capacitance Null Calibration Factor 1000000000 i.e. in integer nF */
    HDWordWriteSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + Cap_Cal_Low_Range_Offset), ((int) (1000000000 * LTestData.Cap_Cal_Low_Range)));
    /* ICutoff Calibration for zero output stored in microvolts */
    HDWordWriteSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + DAC_ICutoff_Zero_Offset), ((int) (1000000 * LTestData.ICutoff_DAC_Zero_OP)));
    /* ICutoff Calibration for 1.9V output stored in microvolts */
    HDWordWriteSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + DAC_ICutoff_1900mV_Offset), ((int) (1000000 * LTestData.ICutoff_DAC_1900mV_OP)));
    /* ADC Calibration full scale voltage stored in microvolts */
    HDWordWriteSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + ADC_Full_Scale_V_Offset), ((int) (1000000 * LTestData.ADC_Full_Scale_V)));
    /* DAC Calibration full scale voltage stored in microvolts */
    HDWordWriteSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + DAC_Full_Scale_V_Offset), ((int) (1000000 * LTestData.DAC_Full_Scale_V)));
}

/****************************************************************************/
/* Do this in one place  -  save memory and hassles with consistency!    	*/
/****************************************************************************/
void Load_From_Memory(char Mem_Bank)
{
    int Temp_Read; /* use this for reading floats stored as int */
    
    /* Read in stored Temp Set for app */
    HDWordReadSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + Temp_Data_Offset), &LTestData.TEMP_DATA, 1 );
    if (LTestData.TEMP_DATA > TEMP_DATA_Max)
        LTestData.TEMP_DATA = TEMP_DATA_Max;
    else if (LTestData.TEMP_DATA < TEMP_DATA_Min)
        LTestData.TEMP_DATA = TEMP_DATA_Min;

    /* test resistor_data - this value is stored in a 32 bit int, in units of milliohms */
    HDWordReadSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + Test_Resistor_Offset), &Temp_Read, 1 );
    LTestData.Test_Current_Resistor = ((float) (Temp_Read)) / 1000000; 
    if (LTestData.Test_Current_Resistor > Test_Resistor_Max)
        LTestData.Test_Current_Resistor = Test_Resistor_Default;
    else if (LTestData.Test_Current_Resistor < Test_Resistor_Min)
        LTestData.Test_Current_Resistor = Test_Resistor_Default;

    /* measurement resistor_data - this value is stored in a 32 bit int with units of micro ohms */
    HDWordReadSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + Meas_Resistor_Offset), &Temp_Read, 1 );
    LTestData.Current_Meas_Resistor = ((float)(Temp_Read)) / 1000000; 
    if (LTestData.Current_Meas_Resistor > Measurement_Resistor_Max)
        LTestData.Current_Meas_Resistor = Measurement_Resistor_Default;
    else if (LTestData.Current_Meas_Resistor < Measurement_Resistor_Min)
        LTestData.Current_Meas_Resistor = Measurement_Resistor_Default;

    /* ISet Calibration Factor at 10mA scaled by 1000000 */
    HDWordReadSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + DAC_ISet_CAL_10mA_Offset), &Temp_Read, 1 );
    LTestData.ISet_CAL_10mA = ((float)(Temp_Read)) / 1000000; 
    if (LTestData.ISet_CAL_10mA > DAC_ISet_10mA_Cal_Max)
        LTestData.ISet_CAL_10mA = DAC_ISet_10mA_Cal_Default;
    else if (LTestData.ISet_CAL_10mA < DAC_ISet_10mA_Cal_Min)
        LTestData.ISet_CAL_10mA = DAC_ISet_10mA_Cal_Default;

    /* ISet Calibration Factor at 100mA scaled by 1000000 */
    HDWordReadSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + DAC_ISet_CAL_100mA_Offset), &Temp_Read, 1 );
    LTestData.ISet_CAL_100mA = ((float)(Temp_Read)) / 1000000; 
    if (LTestData.ISet_CAL_100mA > DAC_ISet_100mA_Cal_Max)
        LTestData.ISet_CAL_100mA = DAC_ISet_100mA_Cal_Default;
    else if (LTestData.ISet_CAL_100mA < DAC_ISet_100mA_Cal_Min)
        LTestData.ISet_CAL_100mA = DAC_ISet_100mA_Cal_Default;

    /* ISet Calibration Factor at 1A scaled by 1000000 */
    HDWordReadSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + DAC_ISet_CAL_1A_Offset), &Temp_Read, 1 );
    LTestData.ISet_CAL_1A = ((float)(Temp_Read)) / 1000000; 
    if (LTestData.ISet_CAL_1A > DAC_ISet_1A_Cal_Max)
        LTestData.ISet_CAL_1A = DAC_ISet_1A_Cal_Default;
    else if (LTestData.ISet_CAL_1A < DAC_ISet_1A_Cal_Min)
        LTestData.ISet_CAL_1A = DAC_ISet_1A_Cal_Default;

    /* Capacitance Null Calibration Factor scaled by 1000000000, i.e. in whole nF */
    HDWordReadSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + Cap_Cal_Low_Range_Offset), &Temp_Read, 1 );
     LTestData.Cap_Cal_Low_Range = ((float)(Temp_Read)) / 1000000000; 
    if (LTestData.Cap_Cal_Low_Range > Cap_Low_Range_Cal_Max)
        LTestData.Cap_Cal_Low_Range = Cap_Low_Range_Cal_Default;
    else if (LTestData.Cap_Cal_Low_Range < Cap_Low_Range_Cal_Min)
        LTestData.Cap_Cal_Low_Range = Cap_Low_Range_Cal_Default;
    
    /* ICutoff DAC output at zero programmed current stored in microvolts */
    HDWordReadSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + DAC_ICutoff_Zero_Offset), &Temp_Read, 1 );
    LTestData.ICutoff_DAC_Zero_OP = ((float)(Temp_Read)) / 1000000; 
    if (LTestData.ICutoff_DAC_Zero_OP > DAC_ICutoff_Zero_Max)
        LTestData.ICutoff_DAC_Zero_OP = DAC_ICutoff_Zero_Default;
    else if (LTestData.ICutoff_DAC_Zero_OP < DAC_ICutoff_Zero_Min)
        LTestData.ICutoff_DAC_Zero_OP = DAC_ICutoff_Zero_Default;

    /* ICutoff DAC output at 1.90V programmed stored in microvolts */
    HDWordReadSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + DAC_ICutoff_1900mV_Offset), &Temp_Read, 1 );
    LTestData.ICutoff_DAC_1900mV_OP = ((float)(Temp_Read)) / 1000000; 
    if (LTestData.ICutoff_DAC_1900mV_OP > DAC_ICutoff_1900mV_Max)
        LTestData.ICutoff_DAC_1900mV_OP = DAC_ICutoff_1900mV_Default;
    else if (LTestData.ICutoff_DAC_1900mV_OP < DAC_ICutoff_1900mV_Min)
        LTestData.ICutoff_DAC_1900mV_OP = DAC_ICutoff_1900mV_Default;

    /* update the DAC cal value in memory from this*/
    LTestData.ICutoff_DAC_Cal = DAC_ICutoff_1900mV_Default/LTestData.ICutoff_DAC_1900mV_OP;
    
    /* ADC Calibration full scale voltage stored in microvolts */
    HDWordReadSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + ADC_Full_Scale_V_Offset), &Temp_Read, 1 );
    LTestData.ADC_Full_Scale_V = ((float)(Temp_Read)) / 1000000; 
    if (LTestData.ADC_Full_Scale_V > ADC_Full_Scale_V_Max)
        LTestData.ADC_Full_Scale_V = ADC_Full_Scale_V_Default;
    else if (LTestData.ADC_Full_Scale_V < ADC_Full_Scale_V_Min)
        LTestData.ADC_Full_Scale_V = ADC_Full_Scale_V_Default;

    /* DAC Calibration full scale voltage stored in micro volts, need to scale back to V*/
    HDWordReadSPI(((LTestData.MemoryBankSelected*ParmSet_Array_Size) + DAC_Full_Scale_V_Offset), &Temp_Read, 1 );
    LTestData.DAC_Full_Scale_V = ((float)(Temp_Read)) / 1000000; 
    if (LTestData.DAC_Full_Scale_V > DAC_Full_Scale_V_Max)
        LTestData.DAC_Full_Scale_V = DAC_Full_Scale_V_Default;
    else if (LTestData.DAC_Full_Scale_V < DAC_Full_Scale_V_Min)
        LTestData.DAC_Full_Scale_V = DAC_Full_Scale_V_Default;
}

/***********************************************************************/
/* Deal with the ADC                                                   */
/* This definitely needs to be modified for the broader application    */
/*      Waits to see ADC Read is complete                              */
/*      Then dumps into LTestData.ADC_CH0[] array in volts             */
/***********************************************************************/
void ReadADC() {
    int i, timeout, startCount;
    
    /* Calculate timeout for waiting for the buffer to fill */
    timeout=(CORE_TIMER_FREQUENCY / 1000U) * ADC_Buffer_Timeout_ms;

    startCount=_CP0_GET_COUNT();
    do {
        // nothing
    }while ((!bufferA_Full) && (!bufferB_Full) && ((_CP0_GET_COUNT() - startCount) < timeout));
    
    /* Print Buffer A ADC results once it is full */
    if (bufferA_Full == true)
    {
        bufferA_Full = false;
        for (i = 0; i < adcSampleCntBuffer[0][0]; i++)
        {
            LTestData.ADC_Ch0[i] = (float)adcResultBuffer[0][0][i] * LTestData.ADC_Full_Scale_V / ADC_MAX_COUNT;
        }

        /* Clear the sample counter */
        adcSampleCntBuffer[0][0] = 0;
    }
    /* Print Buffer B ADC results once it is full */
    if (bufferB_Full == true)
    {
        bufferB_Full = false;
        for (i = 0; i < adcSampleCntBuffer[0][1]; i++)
        {
            LTestData.ADC_Ch0[i] = (float)adcResultBuffer[0][0][i] * LTestData.ADC_Full_Scale_V / ADC_MAX_COUNT;
        }

        /* Clear the sample counter */
        adcSampleCntBuffer[0][1] = 0;
    }
}



/***************************************************************************/
/* initialise stuff                                                        */
/***************************************************************************/
void handleState_INIT() {
    
//    char Temp_String[20],Temp_String2[20] ;
//    int Read_Val;

    // Heartbeat ISR Timer - add later phil
    // User Interface ISR Timer
    /* get user interface ISR timer running*/
    TMR1_Initialize();
//    TMR1_CallbackRegister( UI_InterruptHandler, 0 );
//    TMR1_InterruptEnable();
    TMR1_Start();
    /* set up Timer 2*/
    TMR3_Initialize();
//    TMR3_Start();
    /* initialise data array and check */
    LTest_Initialize ();

    /* SPI2 is the EEPROM */
    SPI2_Initialize ();
    /* SPI1 is the ADAU1467 */
    SPI1_Initialize ();
    /* initialise the EEPROM */
    
    EEPROM_Init(); 
    /* init the DAC to active but nil output*/
    MCP4822_Init();

    /* For completeness - call clear test current*/
    Clear_Test_Current();
    Clear_Cutoff_Current();   
    /* initialise the pulser */
    Initialise_Pulser();
    /* clear discharge output*/
    Discharge_Inactive;
    /* make sure everything is discharged */
    Discharge_DUT();
   
    /**************************************************/
    /* ADC Setup                                      */
    /**************************************************/
    ADCHS_ModulesEnable(ADCHS_MODULE0_MASK | ADCHS_MODULE1_MASK);
    
    /**************************************************/
    /*  set up ISR                                    */
    /**************************************************/ 
    ADCHS_DMACallbackRegister(ADC_ResultHandler, (uintptr_t)NULL);
    ADCHS_DMASampleCountBaseAddrSet((uint32_t)KVA_TO_PA(adcSampleCntBuffer));
    ADCHS_DMAResultBaseAddrSet((uint32_t)KVA_TO_PA(adcResultBuffer));
    /* set the inputs */
    Select_ADC0_Input_To_Read(ADC0_Voltage_Sense_Channel_Select);
    Select_ADC1_Input_To_Read(ADC0_Resistance_Low_Gain_Channel_Select);

    TMR3_Start();
   
    /**********************************************************************/
    /*    NEED TO DEFINE DEFAULT                                          */
    /**********************************************************************/
    Load_From_Memory(LTestData.MemoryBankSelected);   
   
    /* go to LCD Init */
    LTestData.state = Inductor_Tester_STATE_LCDINIT;
    
    /* now lets look at the test rail voltage */
    LTestData.Teat_Rail_V_Meas = (ADC0_Low_Gain()/(Test_Rail_Voltage_Scaling));
}

/******************************************************************************/
/*  Get the LCD running                                             */
/******************************************************************************/
void handleState_LCDINIT() {
   
    /* get the LCD running as debug is nice to have */
    LCD_Boot();
    LCD_Splash_Screen();
    
    if (Key_Pressed() == 1)
    {
        if(!LTestData.Up_Key && !LTestData.Down_Key)  {
            LTestData.state = Inductor_Tester_STATE_CAL_SEL;
            Clear_Key_Pressed();
        }
        else {
            LTestData.state = Inductor_Tester_STATE_IDLE;            
            Clear_Key_Pressed();
        }            
    }
    else
//        LTestData.state = Inductor_Tester_STATE_IDLE;            
//            LTestData.state = Inductor_Tester_STATE_MEASURE_CAP;            
            LTestData.state = Inductor_Tester_STATE_MEASURE_IND;            
//            LTestData.state = Inductor_Tester_STATE_MEASURE_RES;            
        
}

/******************************************************************************/
/*  Handle CAL Entry Check state                                              */
/******************************************************************************/
void handleState_CAL_SEL() {
    char Temp_String[20],Temp_String2[20];
    /* does the user really want this? */
    sprintf(Temp_String, "Calibrate Meter?"); 
    sprintf(Temp_String2,"Yes: Up, No: Dn ");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2);  // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
    LCD_TextOut(0,0,(unsigned char *)Temp_String);   // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
   
    /* wait until the buttons are not pressed */
    do{
        LTestData.UI_Keypressed = 0;
        Let_Bounce_Settle;
        LTestData.UI_Keypressed = Key_Pressed();
    }
    while (LTestData.UI_Keypressed);
    
    /* wait until either Up or Down buttons pressed */
    Let_Bounce_Settle;
    do{}
    while ((!Up) && (!Down));
    
    /* wait for up or down button */
    if (Down) {
        LTestData.state = Inductor_Tester_STATE_IDLE;            
    }
    else if (Up) {
        LTestData.state = Inductor_Tester_STATE_CAL;
    }
}

//******************************************************************************
//*  Handle CALIBRATION                                                        
//  
//  This is a linear process - with no exit.
//  It demands a full CAL be completed in one series of operations
//  But only requires voltage and current measurements - a decent DVM will do
//
//  - LTestData.DAC_ISet_Zero_OP_Current //(zero current in DUT Test)
//  - LTestData.ISet_CAL_10mA //(Measure actual current when set 10mA for the 10mA DUT test)
//  - LTestData.ISet_CAL_100mA   //(Measure actual current when set 100mA for the 100mA DUT test)
//  - LTestData.ISet_CAL_1A   //(Measure actual current when set 1A for the 1A DUT test)
//  - LTestData.DAC_ISet_Zero_OP_Current //( what is the zero voltage output of cutoff DAC?)
//    There are two stackups = the measurement(INA281 + COMP) and
//      the DAC which defines the cutoff current.
//    Worst case for error here is a hight than expected cutoff
//       MCP4822 worst case min o/p = 10mV (which defines the cutoff)
//       INA281 worst case offset input ref = 500uV = 10mV o/p @ G=20
//       LM393 worst case offset = +/-3.5mV
//       If the MCP has 10mV offset and the rest ZERO then minimum cutoff current
//       will be 0.0135/20/0.005 = 135mA
//    Typical values will be less 
//       MCP4822 typical min o/p = 10mV
//       INA281 typical offset input ref = 100uV = 2mV o/p @ G=20
//       LM393 offset = 0.4mV
//       will be 0.01/20/0.005 = 100mA
//
//     For 100mA test cutoff we need  
//       DAC_ICutoff = 0.1 * 0.005 * 20 
//       DAC_ICutoff =  10mV
//     MCP4822 = 2.048V FSD
//       Code = (0.01/2.048)*4095 = 20
//       
//        
//******************************************************************************
void handleState_CAL() {
    int loop_counter = 0;
    char Temp_String[20],Temp_String2[20];

    /* does the user really want this? */
    sprintf(Temp_String, "  CALIBRATION:  "); 
    sprintf(Temp_String2," 6 Steps Follow ");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2); 
    LCD_TextOut(0,0,(unsigned char *)Temp_String);
    CAL_Message_Time;

    sprintf(Temp_String, "Cal kit needed: "); 
    sprintf(Temp_String2,"mV, V, mA and A ");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2); 
    LCD_TextOut(0,0,(unsigned char *)Temp_String);
    CAL_Message_Time;
    

    /* STAGE 1*/
    /* Calibrate DUT test current with ISet_CAL_10mA */
    sprintf(Temp_String, "Stage 1 of Cal "); 
    sprintf(Temp_String2," 10mA Approx   ");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2);
    LCD_TextOut(0,0,(unsigned char *)Temp_String);
    CAL_Message_Time;
    sprintf(Temp_String, "Measure current "); 
    sprintf(Temp_String2,"mA meter as DUT ");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2);
    LCD_TextOut(0,0,(unsigned char *)Temp_String);
    CAL_Message_Time;
    sprintf(Temp_String, "Up/Dn to change "); 
    sprintf(Temp_String2,"Enter when done ");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2); 
    LCD_TextOut(0,0,(unsigned char *)Temp_String); 
    CAL_Message_Time;
    do {
        /* tell the user what is in the data array */
        sprintf(Temp_String, "1: Enter value  "); 
        sprintf(Temp_String2,"Meas %4.1f mA   ", (LTestData.ISet_CAL_10mA*1000));
        LCD_TextOut(1,0,(unsigned char *)Temp_String2);
        LCD_TextOut(0,0,(unsigned char *)Temp_String);

        /* cranks out the test current*/
        Set_Test_Current(DAC_ISet_10mA_Cal);
        CAL_Settle_Time;    
        if (Up){
            LTestData.ISet_CAL_10mA += DAC_ISet_10mA_Cal_Step;
            if (LTestData.ISet_CAL_10mA > DAC_ISet_10mA_Cal_Max)
                LTestData.ISet_CAL_10mA = DAC_ISet_10mA_Cal_Max;
        }
        else if (Down){
            LTestData.ISet_CAL_10mA -= DAC_ISet_10mA_Cal_Step;
            if (LTestData.ISet_CAL_10mA < DAC_ISet_10mA_Cal_Min)
                LTestData.ISet_CAL_10mA = DAC_ISet_10mA_Cal_Min;
        }
    } while (!Enter_Key_Pressed);
    Clear_Test_Current();
    Save_Data_To_Memory();

    /* STAGE 2*/
    /* Calibrate DUT test current to get 100mA, ISet_CAL_100mA */
    sprintf(Temp_String, "Stage 2 of Cal "); 
    sprintf(Temp_String2,"100mA nominal  ");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2);
    LCD_TextOut(0,0,(unsigned char *)Temp_String);
    CAL_Message_Time;
    sprintf(Temp_String, "Measure current "); 
    sprintf(Temp_String2,"mA meter as DUT ");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2);
    LCD_TextOut(0,0,(unsigned char *)Temp_String);
    CAL_Message_Time;
    sprintf(Temp_String, "Up/Dn to change "); 
    sprintf(Temp_String2,"Enter when done ");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2); 
    LCD_TextOut(0,0,(unsigned char *)Temp_String); 
    CAL_Message_Time;
    do {
        /* tell the user what is in the data array */
        sprintf(Temp_String, "2: Enter Value  "); 
        sprintf(Temp_String2,"Meas %5.1f mA   ", (LTestData.ISet_CAL_100mA*1000));
        LCD_TextOut(1,0,(unsigned char *)Temp_String2);
        LCD_TextOut(0,0,(unsigned char *)Temp_String);

        /* cranks out the test current*/
        Set_Test_Current(DAC_ISet_100mA_Cal);
        CAL_Settle_Time;    
        if (Up){
            LTestData.ISet_CAL_100mA += DAC_ISet_100mA_Cal_Step;
            if (LTestData.ISet_CAL_100mA > DAC_ISet_100mA_Cal_Max)
                LTestData.ISet_CAL_100mA = DAC_ISet_100mA_Cal_Max;
        }
        else if (Down){
            LTestData.ISet_CAL_100mA -= DAC_ISet_100mA_Cal_Step;
            if (LTestData.ISet_CAL_100mA < DAC_ISet_100mA_Cal_Min)
                LTestData.ISet_CAL_100mA = DAC_ISet_100mA_Cal_Min;
        }
    } while (!Enter_Key_Pressed);
    Clear_Test_Current();
    Save_Data_To_Memory();

    
    /* STAGE 3*/
    /* Calibrate DUT test current to get 1A, ISet_CAL_1A */
    sprintf(Temp_String, "Stage 3 of Cal "); 
    sprintf(Temp_String2,"1A nominal     ");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2);
    LCD_TextOut(0,0,(unsigned char *)Temp_String);
    CAL_Message_Time;
    /* tell user*/
    sprintf(Temp_String, "Measure current "); 
    sprintf(Temp_String2,"Ammeter as DUT  ");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2);
    LCD_TextOut(0,0,(unsigned char *)Temp_String);
    CAL_Message_Time;
    CAL_Message_Time;
    sprintf(Temp_String, "Pulses o/p 2s on"); 
    sprintf(Temp_String2,"Enter when done ");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2); 
    LCD_TextOut(0,0,(unsigned char *)Temp_String); 
    CAL_Message_Time;
    loop_counter = 0; /* start at zero */
    do {
        /* this bit only enables the test current intermittently */
        /* else things will get HOT in the current source */
        loop_counter += 1; /* increment loop counter */
        /* cranks out the test current*/
        if(loop_counter <= CAL_1A_Ontime){
            Set_Test_Current(DAC_ISet_1A_Cal);
        }
        else {
            Clear_Test_Current();
        };
        
        if (loop_counter > (CAL_1A_Ontime + CAL_1A_Offtime))
            loop_counter = 0;

        /* tell the user what is in the data array */
        sprintf(Temp_String, "3: Enter value  "); 
        sprintf(Temp_String2,"Meas %5.2f Amps ", LTestData.ISet_CAL_1A);
        LCD_TextOut(1,0,(unsigned char *)Temp_String2);
        LCD_TextOut(0,0,(unsigned char *)Temp_String);
        
        CAL_Settle_Time;    
        if (Up){
            LTestData.ISet_CAL_1A += DAC_ISet_1A_Cal_Step;
            if (LTestData.ISet_CAL_1A > DAC_ISet_1A_Cal_Max)
                LTestData.ISet_CAL_1A = DAC_ISet_1A_Cal_Max;
        }
        else if (Down){
            LTestData.ISet_CAL_1A -= DAC_ISet_1A_Cal_Step;
            if (LTestData.ISet_CAL_1A < DAC_ISet_1A_Cal_Min)
                LTestData.ISet_CAL_1A = DAC_ISet_1A_Cal_Min;
        }
    } while (!Enter_Key_Pressed);
    Clear_Test_Current();
    Save_Data_To_Memory();

    /* STAGE 4*/
    sprintf(Temp_String, "Stage 4 of Cal "); 
    sprintf(Temp_String2,"Limit DAC Zero ");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2);
    LCD_TextOut(0,0,(unsigned char *)Temp_String);
    CAL_Message_Time;
    /* Calibrate VSet for DAC set to 0  ICutoff_DAC_Zero_OP */
    sprintf(Temp_String, "Measure voltage "); 
    sprintf(Temp_String2,"at TP6 with DVM ");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2);
    LCD_TextOut(0,0,(unsigned char *)Temp_String);
    CAL_Message_Time;
    sprintf(Temp_String, "Up/Dn to change "); 
    sprintf(Temp_String2,"Enter when done ");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2); 
    LCD_TextOut(0,0,(unsigned char *)Temp_String); 
    CAL_Message_Time;
    loop_counter = 0; /* start at zero */
    do {
        /* tell the user what is in the data array */
        sprintf(Temp_String, "4: Enter value   "); 
        sprintf(Temp_String2,"TP6 Meas %4.1f mV", (1000*LTestData.ICutoff_DAC_Zero_OP));
        LCD_TextOut(1,0,(unsigned char *)Temp_String2);
        LCD_TextOut(0,0,(unsigned char *)Temp_String);

        /* Set ICutoff output to zero */
        Clear_Cutoff_Current();
        CAL_Settle_Time;    
        if (Up) {
            LTestData.ICutoff_DAC_Zero_OP += DAC_ICutoff_Zero_Step;
            if (LTestData.ICutoff_DAC_Zero_OP > DAC_ICutoff_Zero_Max)
                LTestData.ICutoff_DAC_Zero_OP = DAC_ICutoff_Zero_Max;
        }
        else if (Down) {
            LTestData.ICutoff_DAC_Zero_OP -= DAC_ICutoff_Zero_Step;
            if (LTestData.ICutoff_DAC_Zero_OP < DAC_ICutoff_Zero_Min)
                LTestData.ICutoff_DAC_Zero_OP = DAC_ICutoff_Zero_Min;
        }
    } while (!Enter_Key_Pressed);
    Clear_Cutoff_Current();
    Save_Data_To_Memory();

    /* STAGE 5*/
    /* Calibrate VSet = 1900mV          ICutoff_DAC_1900mV_OP */
    /* Update VSet Cal for I cutoff     ICutoff_DAC_cal */
    sprintf(Temp_String, "Stage 5 of Cal "); 
    sprintf(Temp_String2,"Limit DAC Max  ");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2);
    LCD_TextOut(0,0,(unsigned char *)Temp_String);
    CAL_Message_Time;
    sprintf(Temp_String, "Measure voltage "); 
    sprintf(Temp_String2,"at TP6 with DVM ");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2);
    LCD_TextOut(0,0,(unsigned char *)Temp_String);
    CAL_Message_Time;
    sprintf(Temp_String, "Up/Dn to adjust "); 
    sprintf(Temp_String2,"Enter when done ");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2); 
    LCD_TextOut(0,0,(unsigned char *)Temp_String);
    CAL_Message_Time;
    do {
        /* tell the user what is in the data array */
        sprintf(Temp_String, "5: Enter value   "); 
        sprintf(Temp_String2,"TP6 Meas %4.0f mV", (1000*LTestData.ICutoff_DAC_1900mV_OP));
        LCD_TextOut(1,0,(unsigned char *)Temp_String2);
        LCD_TextOut(0,0,(unsigned char *)Temp_String);

        /* cranks out the test voltage from the DAC */
        MCP4822_setVoltage(Current_Cutoff_Channel, DAC_ICutoff_1900mV_Default);
        CAL_Settle_Time;    
        if (Up){
            LTestData.ICutoff_DAC_1900mV_OP += DAC_ICutoff_1900mV_Step;
            if (LTestData.ICutoff_DAC_1900mV_OP > DAC_ICutoff_1900mV_Max)
                LTestData.ICutoff_DAC_1900mV_OP = DAC_ICutoff_1900mV_Max;
        }
        else if (Down){
            LTestData.ICutoff_DAC_1900mV_OP -= DAC_ICutoff_1900mV_Step;
            if (LTestData.ICutoff_DAC_1900mV_OP < DAC_ICutoff_1900mV_Min)
                LTestData.ICutoff_DAC_1900mV_OP = DAC_ICutoff_1900mV_Min;
        }
    } while (!Enter_Key_Pressed);
    Clear_Cutoff_Current();
    Save_Data_To_Memory();
 
    /* STAGE 6*/
    /* Calibrate Capacitance Null */
    /* Stores offset value for low rance cap */
    sprintf(Temp_String, "Stage 6 of Cal  "); 
    sprintf(Temp_String2,"Null capacitance");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2);
    LCD_TextOut(0,0,(unsigned char *)Temp_String);
    CAL_Message_Time;
    sprintf(Temp_String, "Leave DUT open  "); 
    sprintf(Temp_String2,"Until complete..");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2);
    LCD_TextOut(0,0,(unsigned char *)Temp_String);
    CAL_Message_Time;
    sprintf(Temp_String, "Press Enter to  "); 
    sprintf(Temp_String2,"Calibrate       ");
    LCD_TextOut(1,0,(unsigned char *)Temp_String2); 
    LCD_TextOut(0,0,(unsigned char *)Temp_String);
    CAL_Message_Time;    
    do {} 
        while (!Enter_Key_Pressed);   /* wait for the user */
 
    LTestData.Cap_Cal_Low_Range = 0.0; /* TRASH CURRENT CAL */
    handleState_MEASURE_CAP(); 
    
    if ((LTestData.Measured_Const_I_Cap > Cap_Low_Range_Cal_Min) && (LTestData.Measured_Const_I_Cap < Cap_Low_Range_Cal_Max)) {
        LTestData.Cap_Cal_Low_Range = LTestData.Measured_Const_I_Cap;   /* this is a credible measurement */
        Save_Data_To_Memory();
        sprintf(Temp_String, "Null Capacitance"); 
        sprintf(Temp_String2,"Cal done        ");
        LCD_TextOut(1,0,(unsigned char *)Temp_String2); 
        LCD_TextOut(0,0,(unsigned char *)Temp_String);
        CAL_Message_Time;    
    }
    else if (LTestData.Measured_Const_I_Cap < Cap_Low_Range_Cal_Min) {
        sprintf(Temp_String, "Cal Error - Low "); 
        sprintf(Temp_String2,"Measured: %4.0fnF", (LTestData.Measured_Const_I_Cap * 1000000000));
        LCD_TextOut(1,0,(unsigned char *)Temp_String2); 
        LCD_TextOut(0,0,(unsigned char *)Temp_String);
        CAL_Message_Time;            
    }
    else if (LTestData.Measured_Const_I_Cap > Cap_Low_Range_Cal_Max) {
        sprintf(Temp_String, "Cal Error - High "); 
        sprintf(Temp_String2,"Meas: %6.0fnF  ", (LTestData.Measured_Const_I_Cap * 1000000000));
        LCD_TextOut(1,0,(unsigned char *)Temp_String2); 
        LCD_TextOut(0,0,(unsigned char *)Temp_String);
        CAL_Message_Time;            
    }
   
    else;
    
    /* update the DAC cal value in memory from this*/
    LTestData.ICutoff_DAC_Cal = DAC_ICutoff_1900mV_Default/LTestData.ICutoff_DAC_1900mV_OP;
    /* now go to idle */
    LTestData.state = Inductor_Tester_STATE_IDLE;            
}


/******************************************************************************/
/*  Puts IDLE stuff on the screen                                             */
/******************************************************************************/
void Idle_Screen()
{
    char Temp_String[20],Temp_String2[20];

        sprintf(Temp_String, "Idle Screen     "); 
        sprintf(Temp_String2,"blah2           ");


    LCD_TextOut(1,0,(unsigned char *)Temp_String2);  // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
    LCD_TextOut(0,0,(unsigned char *)Temp_String);   // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//    Clear_UI_Input;
    LTestData.UI_Update_Display = 0;  // clear flag display for update
}





/********************************************************************************/
/*                                                                              */
/* Need to watch the DUT terminals and run a constant current through the DUT   */
/*      Start at low current and grab some samples                              */
/*      if value is more than 8% of the max ADC voltage then use that value     */
/*      else go up a current or range step                                      */
/*          10mA, low gain  Measure_High_Resistance()                           */
/*              Max = 3.3/0.01  = 330 Ohms                                      */
/*              8% of 3.3V/0.01A = 26 Ohms                                      */
/*                                                                              */
/*          100mA, low gain   Measure_Medium_Resistance()                       */
/*              maX = 3.1/0.1 = 30 Ohms                                         */
/*              8% of 3.3V/0.1A = 2.4 Ohms                                      */
/*                                                                              */
/*          10mA, High gain  Measure_MedLow_Resistance()                        */
/*              Max = 3.1/(0.01*20) = 15 Ohms                                   */
/*              8% of 3.1V/(0.01A * high gain) = 8% * 3.3/(0.1*20) = 1.2 Ohms   */
/*                                                                              */
/*          100mA, High gain Measure_Low_Resistance()                           */
/*              Max = 3.3/(0.1*20) = 1.5 Ohms                                   */
/*              7% of 3.3V/(0.1A*20) = 0.11 Ohms                                */
/*                                                                              */
/*          1A, High gain  Measure_LowLow_Resistance()                          */
/*              Max = 3.3/20 = 0.15 Ohms                                        */
/*          7% of 3.3V/(1A*20) = 0.011 Ohms                                     */
/********************************************************************************/
void handleState_MEASURE_RES() 
{
    char Temp_String[20],Temp_String2[20];
    float Measured_Resistance;
    
        ADCHS_ModulesDisable ( ADCHS_MODULE1_MASK);    //Stops channel 1

  
    while (1){
    
    
    /* reset the countdown timer */
    LTestData.Revert_To_Idle_Counter = Revert_To_Idle;
    /* turn current sink off */
    Clear_Test_Current();
    /* Discharge the DUT to be sure, then set the Test current to 10mA*/
    Discharge_DUT();
    /* This is not really necessary but sets things in a known state */
    Measure_DUT_Voltage_Low_Gain();
    /* init measurements */
    LTestData.Valid_DC_Resistance = false;      /* start with this as false */
    LTestData.Measured_DC_Resistance = 0.0;     /* start with this as zero which is error */
    LTestData.Next_Range = false;               /* used to watch to see if we want to measure next range */
    Measured_Resistance = 0.0;                  /* start with this at zero */

    /* Stage 1: 10mA test current, Low Gain */
    Measured_Resistance = Measure_High_Resistance();
    if (Measured_Resistance > (High_Resistance_Max)) {
        LTestData.Valid_DC_Resistance = false;
        LTestData.Next_Range = false;        
    }
    else if (Measured_Resistance < (High_Resistance_Threshold)){
        LTestData.Valid_DC_Resistance = false;
        LTestData.Next_Range = true;        
    }
    else if (Measured_Resistance < (High_Resistance_Max)){
        LTestData.Valid_DC_Resistance = true;
        LTestData.Next_Range = false;
    }
    else {
        LTestData.Valid_DC_Resistance = false;
        LTestData.Next_Range = false;        
    }
        
/* Stage 2: 100mA, low gain  */
    if (LTestData.Next_Range ==  true) {
        Measured_Resistance = Measure_Medium_Resistance();
        if (Measured_Resistance < (Medium_Resistance_Threshold)){
            LTestData.Valid_DC_Resistance = false;
            LTestData.Next_Range = true;        
        }
        else {
            LTestData.Valid_DC_Resistance = true;
            LTestData.Next_Range = false;
        }
    }
    
/* Stage 3: 10mA, High gain  */
    if (LTestData.Next_Range ==  true) {
        Measured_Resistance = Measure_MedLow_Resistance();
        if (Measured_Resistance < (MediumLow_Resistance_Threshold)){
            LTestData.Valid_DC_Resistance = false;
            LTestData.Next_Range = true;        
        }
        else{
            LTestData.Valid_DC_Resistance = true;
            LTestData.Next_Range = false;
        }
    }
    
/* Stage 4: 100mA, High gain  */
    if (LTestData.Next_Range ==  true) {
        Measured_Resistance = Measure_Low_Resistance();
        if (Measured_Resistance < (Low_Resistance_Threshold)){
            LTestData.Valid_DC_Resistance = false;
            LTestData.Next_Range = true;        
        }
        else {
            LTestData.Valid_DC_Resistance = true;
            LTestData.Next_Range = false;
        }
    }
    
/* Stage 5: 1A, High gain  */
    if (LTestData.Next_Range ==  true) {
        Measured_Resistance = Measure_LowLow_Resistance();
        LTestData.Valid_DC_Resistance = true;
        LTestData.Next_Range = false;
    }
    
    LTestData.Measured_DC_Resistance = Measured_Resistance;
    
    sprintf(Temp_String, "Voltage: %5.3f  ",LTestData.Scratch); 
    if (LTestData.Valid_DC_Resistance == true) {
        sprintf(Temp_String2,"%10.5f Ohms ",LTestData.Measured_DC_Resistance);
    }
    else{
        sprintf(Temp_String2,"Over Range      ");
    }
    LCD_TextOut(1,0,(unsigned char *)Temp_String2);  // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
    LCD_TextOut(0,0,(unsigned char *)Temp_String);   // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
    CORETIMER_DelayMs(1000);

    } // end of infinite loop
    
}


//******************************************************************************
//
// Need to watch the DUT terminals and look for Capacitor being connected
// The function assumes there is a capacitor across the terminals
// 
// The DMA engine uses two ping pong buffers, A and B
// It dumps 128 samples into each buffer and generates an interrupt when the buffer is full
// the DMA ISR sets bufferA_Full or bufferB_Full flags in the ISR
// 
// Our routine needs to see the flag, then copy the data into a larger array (12k off elements)
// There is 128/3750000 seconds to do this in - which is 34 microseconds
// This needs to run until either the 12800 element array is full or the threshold is found.
//
// From these the capacitance measurement routine
// Finds when the upward slope of measured voltage starts and saves it in "First_Sample_Meas"
// Searches for where the voltage exceeds a set threshold, Cap_Meas_Voltage_ADC_Val then we can stop
// 
// The time between these is "delta T" - Cap_Charge_Time_Counts (in 3.75 MHz clocks)
// The voltage Cap_Meas_Voltage_ADC_Val is "delta V"
// The current is the set test current (10mA, 100mA or 1A)
// 
// given C = Q/V  or C = I/(dv/dt)
// We can calculate C = Set_Test_Current * Cap_Charge_Time_Counts/Cap_Meas_Voltage_ADC_Val
//
//To find the cap:
// start at 10mA
// See if the values make sense
// Else increase
//******************************************************************************
void handleState_MEASURE_CAP() 
{
    char Temp_String[20],Temp_String2[20];
    uint16_t *Meas_Ptr = &LTestData.Meas_Buffer[0];
    int Sample_Cnt = 0;
    int First_Sample_Meas, Final_Sample_Meas = 0;
    bool Overflow = true;
    float Temp_Cap;
    long int Delta_T;
    
    /* reset the countdown timer */
    LTestData.Revert_To_Idle_Counter = Revert_To_Idle;
    /* turn current sink off */
    Clear_Test_Current();
    /* Discharge the DUT to be sure, then set the Test current to 10mA*/
    Discharge_DUT();
    /* sets measurement to low gain across DUT */
    /* Configuration of measurement channel always required */
    Measure_DUT_Voltage_Low_Gain();
    /* init measurements */
    LTestData.Valid_Capacitance = false;        /* start with this as false */
    LTestData.Measured_Const_I_Cap = 0.0;       /* start with this as zero which is error */
    LTestData.Next_Range = false;               /* used to watch to see if we want to measure next range */

   /* init measurements */
    LTestData.Valid_Capacitance = false;        /* start with this as false */
    LTestData.Measured_Const_I_Cap = 0.0;       /* start with this as zero which is error */
    LTestData.Next_Range = false;               /* used to watch to see if we want to measure next range */
    
    /* Stage 1: Low current, high sample rate                           */
    /* ADC_Cap_Buffer_Capture(Sample_Rate_High_Speed, Test_Current_High_Range, Meas_Ptr, &Sample_Cnt , &Overflow); */
    /* C=q/V        C = I/(dV/dt)                                       */
    /* Delta V = 2.0V                                                   */
    /* C = Delta_T * (LTestData.ISet_CAL_10mA / Cap_Meas_Max_Voltage)   */
    /* Min Cap for 25 counts = 0.033uF                                  */
    /* Max Cap for 12800 counts = 17uF                                  */
    Short_DUT(); 
    ADC_Cap_Buffer_Capture(Sample_Rate_High_Speed, Test_Current_High_Range, Meas_Ptr, &Sample_Cnt , &Overflow);
    Short_DUT(); 
    ADC_Cap_Buffer_Find_Thresholds(Meas_Ptr, &First_Sample_Meas, &Final_Sample_Meas);
        Delta_T = (Final_Sample_Meas - First_Sample_Meas);
//    if ((Delta_T > Cap_Meas_Min_Samples) &&  (!Overflow))  {
    if ((!Overflow))  {
        Temp_Cap = ((float)Delta_T/(float)Sample_Rate_High_Speed)* LTestData.ISet_CAL_10mA / (Cap_Meas_Max_Voltage - Cap_Meas_Min_Voltage); 
        Temp_Cap -= LTestData.Cap_Cal_Low_Range;   /* subtract the null capacitance */
        LTestData.Valid_Capacitance = true;
        LTestData.Measured_Const_I_Cap = Temp_Cap;
        LTestData.Next_Range = false;   /* We have a measurement */
    }
    else {
        LTestData.Valid_Capacitance = false;
        LTestData.Measured_Const_I_Cap = 0;       
        LTestData.Next_Range = true;     /* needs longer time or more current */
    }
    
    /* Stage 2: Low current, medium sample rate                           */
    /* ADC_Cap_Buffer_Capture(Sample_Rate_Medium_Speed, Test_Current_High_Range, Meas_Ptr, &Sample_Cnt , &Overflow); */
    /* C=q/V        C = I/(dV/dt)                                       */
    /* Delta V = 2.0V                                                   */
    /* C = Delta_T * (LTestData.ISet_CAL_10mA / Cap_Meas_Max_Voltage)   */
    /* Min Cap for 25 counts = 0.33uF                                  */
    /* Max Cap for 12800 counts = 170uF                                  */

    if(LTestData.Next_Range == true) {
        ADC_Cap_Buffer_Capture(Sample_Rate_Medium_Speed, Test_Current_High_Range, Meas_Ptr, &Sample_Cnt , &Overflow);
        Short_DUT(); 
        ADC_Cap_Buffer_Find_Thresholds(Meas_Ptr, &First_Sample_Meas, &Final_Sample_Meas);
        Delta_T = (Final_Sample_Meas - First_Sample_Meas);
        if ((Delta_T > Cap_Meas_Min_Samples) &&  (!Overflow))  {
            Temp_Cap = ((float)Delta_T/(float)Sample_Rate_Medium_Speed)* LTestData.ISet_CAL_10mA / (Cap_Meas_Max_Voltage - Cap_Meas_Min_Voltage); 
            LTestData.Valid_Capacitance = true;
            LTestData.Measured_Const_I_Cap = Temp_Cap;
            LTestData.Next_Range = false;   /* We have a measurement */
        }
        else {
            LTestData.Valid_Capacitance = false;
            LTestData.Measured_Const_I_Cap = 0;       
            LTestData.Next_Range = true;     /* needs longer time or more current */
        }    
    }
    
    /* Stage 3: Low current, Low sample rate                           */
    /* ADC_Cap_Buffer_Capture(Sample_Rate_Low_Speed, Test_Current_High_Range, Meas_Ptr, &Sample_Cnt , &Overflow); */
    /* C=q/V        C = I/(dV/dt)                                       */
    /* Delta V = 2.0V                                                   */
    /* C = Delta_T * (LTestData.ISet_CAL_10mA / Cap_Meas_Max_Voltage)   */
    /* Min Cap for 25 counts = 3.3uF                                  */
    /* Max Cap for 12800 counts = 1700uF                                  */
    if(LTestData.Next_Range == true) {
        ADC_Cap_Buffer_Capture(Sample_Rate_Low_Speed, Test_Current_High_Range, Meas_Ptr, &Sample_Cnt , &Overflow);
        Short_DUT(); 
        ADC_Cap_Buffer_Find_Thresholds(Meas_Ptr, &First_Sample_Meas, &Final_Sample_Meas);
        Delta_T = (Final_Sample_Meas - First_Sample_Meas);
        if ((Delta_T > Cap_Meas_Min_Samples) &&  (!Overflow))  {
            Temp_Cap = ((float)Delta_T/(float)Sample_Rate_Low_Speed)* LTestData.ISet_CAL_10mA / (Cap_Meas_Max_Voltage - Cap_Meas_Min_Voltage); 
            LTestData.Valid_Capacitance = true;
            LTestData.Measured_Const_I_Cap = Temp_Cap;
            LTestData.Next_Range = false;   /* We have a measurement */
        }
        else {
            LTestData.Valid_Capacitance = false;
            LTestData.Measured_Const_I_Cap = 0;       
            LTestData.Next_Range = true;     /* needs longer time or more current */
        }    
    }
   
    /* Stage 4: Medium current, Low sample rate                           */
    /* ADC_Cap_Buffer_Capture(Sample_Rate_Low_Speed, Test_Current_Medium_Range, Meas_Ptr, &Sample_Cnt , &Overflow); */
    /* C=q/V        C = I/(dV/dt)                                       */
    /* Delta V = 2.0V                                                   */
    /* C = Delta_T * (LTestData.ISet_CAL_100mA / Cap_Meas_Max_Voltage)   */
    /* Min Cap for 25 counts = 33uF                                  */
    /* Max Cap for 12800 counts = 17000uF                                  */
    if(LTestData.Next_Range == true) {
        ADC_Cap_Buffer_Capture(Sample_Rate_Low_Speed, Test_Current_Medium_Range, Meas_Ptr, &Sample_Cnt , &Overflow);
        Short_DUT(); 
        ADC_Cap_Buffer_Find_Thresholds(Meas_Ptr, &First_Sample_Meas, &Final_Sample_Meas);
        Delta_T = (Final_Sample_Meas - First_Sample_Meas);
        if ((Delta_T > Cap_Meas_Min_Samples) &&  (!Overflow))  {
            Temp_Cap = ((float)Delta_T/(float)Sample_Rate_Low_Speed)* LTestData.ISet_CAL_100mA / (Cap_Meas_Max_Voltage - Cap_Meas_Min_Voltage); 
            LTestData.Valid_Capacitance = true;
            LTestData.Measured_Const_I_Cap = Temp_Cap;
            LTestData.Next_Range = false;   /* We have a measurement */
        }
        else {
            LTestData.Valid_Capacitance = false;
            LTestData.Measured_Const_I_Cap = 0;       
            LTestData.Next_Range = true;     /* needs longer time or more current */
        }    
    }

    /* Stage 5: High current, Low sample rate                           */
    /* ADC_Cap_Buffer_Capture(Sample_Rate_Low_Speed, Test_Current_Low_Range, Meas_Ptr, &Sample_Cnt , &Overflow); */
    /* C=q/V        C = I/(dV/dt)                                       */
    /* Delta V = 2.0V                                                   */
    /* C = Delta_T * (LTestData.ISet_CAL_1A / Cap_Meas_Max_Voltage)   */
    /* Min Cap for 25 counts = 330uF                                  */
    /* Max Cap for 12800 counts = 170000uF                                  */
    if(LTestData.Next_Range == true) {
        ADC_Cap_Buffer_Capture(Sample_Rate_Low_Speed, Test_Current_Low_Range, Meas_Ptr, &Sample_Cnt , &Overflow);
        Short_DUT(); 
        ADC_Cap_Buffer_Find_Thresholds(Meas_Ptr, &First_Sample_Meas, &Final_Sample_Meas);
        Delta_T = (Final_Sample_Meas - First_Sample_Meas);
        if ((Delta_T > Cap_Meas_Min_Samples) &&  (!Overflow))  {
            Temp_Cap = ((float)Delta_T/(float)Sample_Rate_Low_Speed)* LTestData.ISet_CAL_1A / (Cap_Meas_Max_Voltage - Cap_Meas_Min_Voltage); 
            LTestData.Valid_Capacitance = true;
            LTestData.Measured_Const_I_Cap = Temp_Cap;
            LTestData.Next_Range = false;   /* We have a measurement */
        }
        else {
            LTestData.Valid_Capacitance = false;
            LTestData.Measured_Const_I_Cap = 0;       
            LTestData.Next_Range = true;     /* needs longer time or more current */
        }    
    }

    if (LTestData.Valid_Capacitance == true)
    {
        Delta_T = Final_Sample_Meas - First_Sample_Meas;
        if (LTestData.Measured_Const_I_Cap < 1E-6)
            sprintf(Temp_String2,"%6.1fnF   ", (LTestData.Measured_Const_I_Cap * 1000000000));
        else if (LTestData.Measured_Const_I_Cap < 1E-1)
            sprintf(Temp_String2,"%6.1fuF   ", (LTestData.Measured_Const_I_Cap * 1000000));
        else
            sprintf(Temp_String2,"%6.5fF  %ld ", (LTestData.Measured_Const_I_Cap), Delta_T);
        sprintf(Temp_String, "%u %d %d  ", TMR3_PeriodGet(),First_Sample_Meas, Final_Sample_Meas); 
//            sprintf(Temp_String2,"Meas %6.4f     ",LTestData.V_Meas_100us);
    LCD_TextOut(1,0,(unsigned char *)Temp_String2);  // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
    LCD_TextOut(0,0,(unsigned char *)Temp_String);   // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
    CORETIMER_DelayMs(1000);    
    }
    

}



//******************************************************************************
//
// This function assumes there is an inductor across the terminals
// 
// The DMA engine uses two ping pong buffers, A and B
// It dumps 128 samples into each buffer and generates an interrupt when the buffer is full
// the DMA ISR sets bufferA_Full or bufferB_Full flags in the ISR
// 
// Our routine needs to see the flag, then copy the data into a larger array (12k off elements)
// There is 128/3750000 seconds to do this in - which is 34 microseconds
// This needs to run until either the 12800 element array is full or the threshold is found.
//
// The system will hold a short across the inductor using the DISCHARGE FET
// When the short is there the voltage across the DUT = 0
// As the inductor current increases the voltage across the inductor will be the full rail
// Once the current reaches the constant current level, the voltage will fall to the V = I x R 
// 
// By measuring the time that the inductor has the 10V rail across it, we can estimate the inductance
// from the formula L = V/(di/dt)
// 
//
//******************************************************************************
void handleState_MEASURE_IND() 
{
    char Temp_String[20],Temp_String2[20];
    uint16_t *Meas_Ptr = &LTestData.Meas_Buffer[0];
//    int Sample_Cnt = 0;
//    int First_Sample_Meas, Final_Sample_Meas = 0;
//    bool Overflow = true;
//    float Temp_Ind;
//    long int Delta_T;
    
    /* reset the countdown timer */
    LTestData.Revert_To_Idle_Counter = Revert_To_Idle;
    /* turn current sink off */
    Clear_Test_Current();
    /* Discharge the DUT to be sure, then set the Test current to 10mA*/
    Discharge_DUT();
    Short_DUT();  // we want the DUT shorted and the current source to stabilise
    Set_Test_Current(Test_Current_High_Range);   /* 10mA */
    Inductance_Current_Settle;
    
   
    do {
        Set_Test_Current(Test_Current_Low_Range);   /* 1A */

        ADC_Ind_Buffer_Capture(Sample_Rate_High_Speed, Meas_Ptr);
    Clear_Test_Current();

        
    sprintf(Temp_String2,"%d         ", LTestData.Meas_Buffer[0]);
    sprintf(Temp_String, "%d         ",LTestData.Meas_Buffer[100]); 
    LCD_TextOut(1,0,(unsigned char *)Temp_String2);  // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
    LCD_TextOut(0,0,(unsigned char *)Temp_String);   // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
    Short_DUT();
    CORETIMER_DelayMs(1000);    
 
            
    } while (1);
    

}






//******************************************************************************
//
// Need to watch the DUT terminals and look for something being connected
// Once see something, then decide what it is
//
//******************************************************************************
void handleState_IDLE() 
{
    char Temp_String[20],Temp_String2[20];
    long int time_cnt, time_cnt1;
    uint16_t *Meas_Ptr = &LTestData.Meas_Buffer[0];
    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, Sample_Cnt = 0;
    int First_Sample_Meas, Final_Sample_Meas = 0;
    int Cap_Charge_Time_Counts;
    bool Threshold_Found, Final_Samples = false;
    bool First_Sample_Found, Final_Sample_Found = false;
    bool Overflow = true;
    
//    float Measured_Resistance;
        
    /* reset the countdown timer */
    LTestData.Revert_To_Idle_Counter = Revert_To_Idle;
    /* Discharge the DUT to be sure, then set the Test current to 10mA*/
    Discharge_DUT();
//    Set_Test_Current(LTestData.ISet_CAL_1A*Test_Current_Low_Range);
//    Set_Test_Current(LTestData.ISet_CAL_100mA*Test_Current_Medium_Range);
//    Set_Test_Current(LTestData.ISet_CAL_10mA*Test_Current_High_Range);
    MCP4822_Settle_Time;
    
    
    /* THIS IS TEST CODE - NEEDS TO BE REPLACED WITH IDLE STATE CODE */
    /* THIS IS TEST CODE - NEEDS TO BE REPLACED WITH IDLE STATE CODE */
    /* THIS IS TEST CODE - NEEDS TO BE REPLACED WITH IDLE STATE CODE */
    Idle_Screen();
//    Select_ADC0_Input_To_Read(ADC0_Resistance_Hi_Gain_Channel_Select);
//    Measure_Test_Voltage_Rail();
    Measure_DUT_Voltage_Low_Gain();
//    Measure_DUT_Voltage_High_Gain();


while (true)
{
//    Measured_Resistance = Measure_High_Resistance();
//             sprintf(Temp_String, "High Resist Meas"); 
//             sprintf(Temp_String2,"R = %6.3f       ",Measured_Resistance);
//             LCD_TextOut(1,0,(unsigned char *)Temp_String2);  // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//            LCD_TextOut(0,0,(unsigned char *)Temp_String);   // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//            CORETIMER_DelayMs(2000);
//
//    Measured_Resistance = Measure_Medium_Resistance();
//            sprintf(Temp_String, "Med Resist Meas "); 
//            sprintf(Temp_String2,"R = %6.3f       ",Measured_Resistance);
//             LCD_TextOut(1,0,(unsigned char *)Temp_String2);  // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//            LCD_TextOut(0,0,(unsigned char *)Temp_String);   // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//            CORETIMER_DelayMs(2000);
//    Measured_Resistance = Measure_Low_Resistance();
//             sprintf(Temp_String, "Low Resist Meas "); 
//             sprintf(Temp_String2,"R = %6.3f       ",Measured_Resistance);
//            LCD_TextOut(1,0,(unsigned char *)Temp_String2);  // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//            LCD_TextOut(0,0,(unsigned char *)Temp_String);   // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//             CORETIMER_DelayMs(2000);
//    Measured_Resistance = Measure_LowLow_Resistance();
//             sprintf(Temp_String, "LowLow Res Meas "); 
//             sprintf(Temp_String2,"R = %6.3f       ",Measured_Resistance);
//            LCD_TextOut(1,0,(unsigned char *)Temp_String2);  // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//            LCD_TextOut(0,0,(unsigned char *)Temp_String);   // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//             CORETIMER_DelayMs(2000);
Clear_Test_Current();
//    Set_Test_Current(Test_Current_High_Range*LTestData.ISet_CAL_10mA);   /* 10mA */
//    Set_Test_Current(Test_Current_Medium_Range*LTestData.ISet_CAL_100mA);   /* 100mA */
    
//    CORETIMER_DelayMs(100);
//    Measure_DUT_Voltage_Low_Gain(); 

    Discharge_DUT();
//    Short_DUT();
//    bufferA_Full = false;
//    bufferB_Full = false;
//    while ((!bufferA_Full) || (!bufferB_Full)) {
//      //do nothing  
//    };
//     LTestData.V_Meas_1us = ADC0_Low_Gain_Quick();
//    Short_DUT();
//    bufferA_Full = false;
//    bufferB_Full = false;
//    while ((!bufferA_Full) || (!bufferB_Full)) {
//      //do nothing  
//    };
//     CORETIMER_DelayUs(10);
//    LTestData.V_Meas_10us = ADC0_Low_Gain_Quick();
//    Short_DUT();
//    bufferA_Full = false;
//    bufferB_Full = false;
//    while ((!bufferA_Full) || (!bufferB_Full)) {
//      //do nothing  
//    };
//    ADCHS_ModulesDisable(ADCHS_MODULE0_MASK | ADCHS_MODULE1_MASK);
//    Set_Test_Current(Test_Current_Low_Range*LTestData.ISet_CAL_1A);   /* 1000mA */
//    Set_Test_Current(Test_Current_High_Range*LTestData.ISet_CAL_10mA);   /* 10mA */
//    Set_Test_Current(Test_Current_Medium_Range*LTestData.ISet_CAL_100mA);   /* 100mA */

    //try me
//    ADCHS_ModulesDisable (ADCHS_MODULE0_MASK | ADCHS_MODULE1_MASK);
    ADCHS_ModulesDisable ( ADCHS_MODULE1_MASK);
    ADCDSTATbits.DMACEN = 0;
    ADCDSTATbits.DMAEN = 0;
            
//    ADCDSTAT = ADCDSTAT & 0x8fffffff;
    Short_DUT_1ms();
//    ADCDSTAT = ADCDSTAT | 0x10000000;
    //try me
    // this shjould reset the DMA engine 
//    ADCHS_ModulesEnable (ADCHS_MODULE0_MASK | ADCHS_MODULE1_MASK);
//    ADCDSTATbits.DMACEN = 1;
//    ADCDSTATbits.DMAEN = 1;
//    CORETIMER_DelayUs(10);
//    time_cnt = _CP0_GET_COUNT();
//    ADCHS_ModulesEnable(ADCHS_MODULE0_MASK | ADCHS_MODULE1_MASK);
    bufferA_Full = false;
    bufferB_Full = false;
//    while ((!bufferA_Full) || (!bufferB_Full)) {
//        // do nothing
//    }
     LTestData.V_Meas_100us = (float)ADCDATA0 * LTestData.ADC_Full_Scale_V / ADC_MAX_COUNT;
     
     /* number of samples in the buffer*/
     Sample_Cnt = 0;
     BufA_Ptr = BufA_Ptr_Rst;
     BufB_Ptr = BufB_Ptr_Rst;
     Meas_Ptr_Cntr = Buffer_Size;
     Meas_Ptr = &LTestData.Meas_Buffer[0];
     
    ADCDSTATbits.DMACEN = 1;
    ADCDSTATbits.DMAEN = 1;
//    Set_Test_Current(Test_Current_Medium_Range*LTestData.ISet_CAL_100mA);   /* 100mA */
    Set_Test_Current(Test_Current_Medium_Range);   /* 100mA */
    time_cnt = _CP0_GET_COUNT();
   
    Threshold_Found = false;
    Final_Samples = true;
    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;
         }
        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; 
        }
     }
    time_cnt1 = _CP0_GET_COUNT();   
  
    Clear_Test_Current();
    Short_DUT();
  
     
//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

    if (!Overflow)    Cap_Charge_Time_Counts = Final_Sample_Meas - First_Sample_Meas;
    else Cap_Charge_Time_Counts = 666;

    
     LTestData.V_Meas_1ms = (float)ADCDATA0 * LTestData.ADC_Full_Scale_V / ADC_MAX_COUNT;;

//     LTestData.V_Meas_100us = (float)adcResultBuffer[0][1][0] * LTestData.ADC_Full_Scale_V / ADC_MAX_COUNT;
//     LTestData.V_Meas_1ms = (float)adcResultBuffer[0][0][0] * LTestData.ADC_Full_Scale_V / ADC_MAX_COUNT;;
//    LTestData.V_Meas_100us = ADC0_Low_Gain_Quick();
//    Short_DUT();
//    CORETIMER_DelayMs(1);
//    LTestData.V_Meas_1ms = ADC0_Low_Gain_Quick();
//    Short_DUT();
//    CORETIMER_DelayMs(10);
//    LTestData.V_Meas_10ms = ADC0_Low_Gain_Quick();
//    Short_DUT();
//    CORETIMER_DelayMs(100);
//    LTestData.V_Meas_100ms = ADC0_Low_Gain_Quick();
//    Short_DUT();
//    CORETIMER_DelayMs(1000);
//    LTestData.V_Meas_1000ms = ADC0_Low_Gain_Quick();
//    
//            sprintf(Temp_String, "1us             "); 
//            sprintf(Temp_String2,"Meas %6.4f     ",LTestData.V_Meas_1us);
//            LCD_TextOut(1,0,(unsigned char *)Temp_String2);  // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//            LCD_TextOut(0,0,(unsigned char *)Temp_String);   // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//            CORETIMER_DelayMs(3000);
//
//            sprintf(Temp_String, "10us            "); 
//            sprintf(Temp_String2,"Meas %6.4f     ",LTestData.V_Meas_10us);
//            LCD_TextOut(1,0,(unsigned char *)Temp_String2);  // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//            LCD_TextOut(0,0,(unsigned char *)Temp_String);   // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//            CORETIMER_DelayMs(3000);
//
            sprintf(Temp_String, "%ld %d %d", time_cnt1-time_cnt,Final_Sample_Meas, (int)(Cap_Charge_Time_Counts)); 
            sprintf(Temp_String2,"%6.4f %6.4f   ",LTestData.V_Meas_100us, LTestData.V_Meas_1ms);
//            sprintf(Temp_String2,"Meas %6.4f     ",LTestData.V_Meas_100us);
            LCD_TextOut(1,0,(unsigned char *)Temp_String2);  // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
            LCD_TextOut(0,0,(unsigned char *)Temp_String);   // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
            CORETIMER_DelayMs(1000);

//            sprintf(Temp_String, "1ms             "); 
//            sprintf(Temp_String2,"Meas %6.4f     ",LTestData.V_Meas_1ms);
//            LCD_TextOut(1,0,(unsigned char *)Temp_String2);  // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//            LCD_TextOut(0,0,(unsigned char *)Temp_String);   // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//            CORETIMER_DelayMs(3000);
            
//            sprintf(Temp_String, "10ms            "); 
//            sprintf(Temp_String2,"Meas %6.4f     ",LTestData.V_Meas_10ms);
//            LCD_TextOut(1,0,(unsigned char *)Temp_String2);  // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//            LCD_TextOut(0,0,(unsigned char *)Temp_String);   // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//            CORETIMER_DelayMs(3000);
//            
//            sprintf(Temp_String, "100ms           "); 
//            sprintf(Temp_String2,"Meas %6.4f     ",LTestData.V_Meas_100ms);
//            LCD_TextOut(1,0,(unsigned char *)Temp_String2);  // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//            LCD_TextOut(0,0,(unsigned char *)Temp_String);   // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//            CORETIMER_DelayMs(3000);

//            sprintf(Temp_String, "1000ms          "); 
//            sprintf(Temp_String2,"Meas %6.4f     ",LTestData.V_Meas_1000ms);
//            LCD_TextOut(1,0,(unsigned char *)Temp_String2);  // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//            LCD_TextOut(0,0,(unsigned char *)Temp_String);   // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
//            CORETIMER_DelayMs(3000);
            
            
}    
    Select_ADC1_Input_To_Read(ADC1_Inductor_Current_Channel_Select);
    while(true)
    {
            sprintf(Temp_String, "ADC0 = %6.3f   ",ADC0_Low_Gain()); 
//            sprintf(Temp_String, "ADC0 = %6.3f BB",(float)((float)adcResultBuffer[0][1][0]*ADC_Full_Scale_V_Default*((VSense_Divider_Bottom + VSense_Divider_Top)/VSense_Divider_Bottom)/ADC_MAX_COUNT)); 
            sprintf(Temp_String2,"ADC1 = %6.3f   ",Current_Sense_Voltage());
//            sprintf(Temp_String2,"ADC1 = %6.3f BB",(float)((float)adcResultBuffer[1][1][ADC1_Cnt]*ADC_Full_Scale_V_Default/ADC_MAX_COUNT));
            LCD_TextOut(1,0,(unsigned char *)Temp_String2);  // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized
            LCD_TextOut(0,0,(unsigned char *)Temp_String);   // could be optimized//        LCD_TextOut(1,0,(unsigned char *)Temp_String);   // could be optimized

        CORETIMER_DelayMs(1000);
    }



    
}



// *****************************************************************************
// *****************************************************************************
// Section: Polled State Machine
//  STATE: Init
//          - set up timers
//          - set i/o up (GPIO and SPI)
//          - open comms to EEPROM
//          - Load EEPROM and default all parameters
//          - Next state is LCD init
//  STATE:LCDInit
//          - get the LCD initialised
//          - Put up splash
//          - goto idle screen
//          - Next state is IDLE
//  STATE:IDLE
// *****************************************************************************
// *****************************************************************************
void Inductor_Tester_Tasks(void)
{
    
do{
    
    /* keep track of how often we run through the loop */
    //    PreampData.UI_Update_Counter++;

    /* clear WatchDFof Timer*/
    //WDTCONSET = 0x01;
    WDT_Clear();
    
    if (LTestData.heartbeatCount) {
        LTestData.heartbeatCount--;
    }
    else  {
        LTestData.heartbeatCount = HeartbeatCountInit; 
        /* Signal the application's heartbeat. */
        if (LTestData.heartbeatToggle == true) {
            /* ADD code to reset heartbeat */
            LTestData.heartbeatToggle = false;
        }
        else {
            LTestData.heartbeatToggle = true;        
        }        
    }

        /* Check the application's current state. */
    switch ( LTestData.state )
    {
        /* Application's initial state. */
        case Inductor_Tester_STATE_INIT:
            handleState_INIT();
            break;
        case Inductor_Tester_STATE_LCDINIT:
            handleState_LCDINIT();
            break;
        case Inductor_Tester_STATE_CAL_SEL:
            handleState_CAL_SEL();
            break;
        case Inductor_Tester_STATE_CAL:
            handleState_CAL();
            break;
        case Inductor_Tester_STATE_IDLE:
            handleState_IDLE();
            break;
        case Inductor_Tester_STATE_MEASURE_CAP:
            handleState_MEASURE_CAP();
            break;
        case Inductor_Tester_STATE_MEASURE_RES:
            handleState_MEASURE_RES();
            break;
        case Inductor_Tester_STATE_MEASURE_IND:
            handleState_MEASURE_IND();
            break;         default:
            /* TODO: Handle error in application's state machine. */
        break;
    }

    /* decrement this outside the UI loop, if it gets to zero then */
    /* the UI will reset the fast counter and not got to fast change */
    if(LTestData.UI_Slow_Count > 0)
        LTestData.UI_Slow_Count--;

    /* latch key_pressed into UI_Keypressed*/
    if(Key_Pressed())
    {
       LTestData.UI_Keypressed = true;       
    }

  } while (1);
}



/*******************************************************************************
 End of File
*/

