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

 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 <math.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 = 0;  // flag display for update
}

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

  Remarks:
    See prototype in Inductor_Tester.h.
 *  I just want sensible data in here before I load stuff.
 *  That is perhaps paranoid - but a couple of variables are not loaded from ROM
******************************************************************************/
void LTest_Initialize ( void )
{
    int i;
    /* Place the App state machine in its initial state. */
    LTestData.state = Inductor_Tester_STATE_INIT;
    LTestData.Meas_Action = Measurement_Resistance;   
    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.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.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.Valid_Sat_I = false;
    LTestData.Next_Range = false;
    LTestData.Measured_10pc_Sat_I = 0.0;
    LTestData.Measured_20pc_Sat_I = 0.0;
    LTestData.Cap_Cal_Low_Range = 0.0;
    LTestData.Test_Rail_V_Meas = 0.0;
    LTestData.Inductance_Sat_Step = 0;
    LTestData.Inductance_At_Step = 0.0;
    
    for(i=0; i<Num_Sat_Samples; i++) {
        LTestData.Measured_Sat_Current_Results[0][i] = 0.0; // current
        LTestData.Measured_Sat_Current_Results[1][i] = 0.0; // inductance       
    }
    
    /* 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)));
    /* 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!    	*/
/*   Lots of bounds checking                                                */
/****************************************************************************/
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;
    
    /* 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;
}


/***************************************************************************/
/* initialise stuff                                                        */
/***************************************************************************/
void handleState_INIT() {
    
    // Heartbeat ISR Timer - add later phil
    // User Interface ISR Timer
    /* get user interface ISR timer running*/
    TMR3_Initialize();
    /* 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();
    /* The ADC subsystem is intialised by the Harmony function          */
    /* It gets this bit wrong for using DMA...                          */
    /* The code sets ADCSEL = 0x0, which SHOULD be the same as 0x11     */
    /* as both are SYSCLK, but with 00, DMA transfers for multiple      */
    /* channels seem to terminate half way through                      */
    /*  Grrrrrr                                                         */
    ADCCON3bits.ADCSEL = 3;  // stated as essential for DMA
    /* 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);

    /* start the timer for the ADC */
    TMR3_Start();
   
    /**********************************************************************/
    /*    NEED TO DEFINE DEFAULT                                          */
    /**********************************************************************/
    Load_From_Memory(LTestData.MemoryBankSelected);   
  
    /* read the rail sense */
    Select_ADC0_Input_To_Read(ADC0_Voltage_Sense_Channel_Select);
    /* now lets look at the test rail voltage */
    CORETIMER_DelayMs(Inductance_Measurement_Rail_Meas_Settle);
    LTestData.Test_Rail_V_Meas = (ADC0_Low_Gain()/(Test_Rail_Voltage_Scaling));
    /* go to LCD Init */
    LTestData.state = Inductor_Tester_STATE_LCDINIT;    
}

/******************************************************************************/
/*  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{
        /* present idle screen */
        Idle_Screen();
        LTestData.state = Inductor_Tester_STATE_IDLE;            
    }
}

/******************************************************************************/
/*  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);  
    LCD_TextOut(0,0,(unsigned char *)Temp_String);   
   
    /* 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) {
        /* present idle screen */
        Idle_Screen();
        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," 5 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.3f 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*/
    /* Calibrate 3.3VA = 3300mV nominal */
    sprintf(Temp_String, "Stage 4 of Cal "); 
    sprintf(Temp_String2,"Measure 3.3VA  ");
    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 TP8 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, "4: Enter value  "); 
        sprintf(Temp_String2,"TP8 Meas %4.0f mV", (1000*LTestData.ADC_Full_Scale_V));
        LCD_TextOut(1,0,(unsigned char *)Temp_String2);
        LCD_TextOut(0,0,(unsigned char *)Temp_String);
        CAL_Settle_Time;    

        /* get  user input */
        if (Up){
            LTestData.ADC_Full_Scale_V += ADC_Full_Scale_V_Step;
            if (LTestData.ADC_Full_Scale_V > ADC_Full_Scale_V_Max)
                LTestData.ADC_Full_Scale_V = ADC_Full_Scale_V_Max;
        }
        else if (Down){
            LTestData.ADC_Full_Scale_V -= ADC_Full_Scale_V_Step;
            if (LTestData.ADC_Full_Scale_V < ADC_Full_Scale_V_Min)
                LTestData.ADC_Full_Scale_V = ADC_Full_Scale_V_Min;
        }
    } while (!Enter_Key_Pressed);
    Clear_Cutoff_Current();
    Save_Data_To_Memory();

        
    /* STAGE 5*/
    /* Calibrate Capacitance Null */
    /* Stores offset value for low rance cap */
    sprintf(Temp_String, "Stage 5 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;

    
    
    /* present idle screen */
    Idle_Screen();
    /* 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, "Up/Dn to select:");
        if (LTestData.Meas_Action == Measurement_Idle){
            sprintf(Temp_String2, "Idle            ");
        }
        else if (LTestData.Meas_Action == Measurement_Resistance){
            sprintf(Temp_String,  "Resistance <330R");
            sprintf(Temp_String2, "Enter to Meas   ");
        }
        else if (LTestData.Meas_Action == Measurement_Capacitance){
            sprintf(Temp_String,  "Capacitance     ");
            sprintf(Temp_String2, "Enter to Meas   ");
        }
        else if (LTestData.Meas_Action == Measurement_Inductance_I){
            sprintf(Temp_String,  "Inductance >50uH");
            sprintf(Temp_String2, "Enter to Meas   ");
        }
        else if (LTestData.Meas_Action == Measurement_Inductance_Sat){
            sprintf(Temp_String,  "Inductor Sat'n  ");
            sprintf(Temp_String2, "Enter to Meas   ");
        }

    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
}


/******************************************************************************/
/*  User has pressed Enter - let them know we are acting                      */
/******************************************************************************/
void Acting_On_Idle_Screen()
{
    char Temp_String[20],Temp_String2[20];

        sprintf(Temp_String,      "Measuring:      ");
        if (LTestData.Meas_Action == Measurement_Idle){
            sprintf(Temp_String2, "Oops thats weird");
        }
        else if (LTestData.Meas_Action == Measurement_Resistance){
            sprintf(Temp_String2, "Resistance      ");
        }
        else if (LTestData.Meas_Action == Measurement_Capacitance){
            sprintf(Temp_String2, "Capacitance     ");
        }
        else if (LTestData.Meas_Action == Measurement_Inductance_I){
            sprintf(Temp_String2, "Inductance      ");
        }
        else if (LTestData.Meas_Action == Measurement_Inductance_Sat){
            sprintf(Temp_String2, "Inductance Sat'n");
        }

    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
}

/******************************************************************************/
/*  put results onto the screen                                               */
/******************************************************************************/
void Display_Results()
{
    char Temp_String[20],Temp_String2[20];

        if (LTestData.Meas_Action == Measurement_Idle){
            sprintf(Temp_String,  "Up/Dn to select:");
            sprintf(Temp_String2, "Measurement     ");
        }
        else if (LTestData.Meas_Action == Measurement_Resistance){
            if (LTestData.Valid_DC_Resistance == true){
                sprintf(Temp_String,  "Resistance:     ");
                if (LTestData.Measured_DC_Resistance > 100)
                    sprintf(Temp_String2,"%5.1f Ohms      ",LTestData.Measured_DC_Resistance);
                else if (LTestData.Measured_DC_Resistance > 10)
                    sprintf(Temp_String2,"%5.2f Ohms      ",LTestData.Measured_DC_Resistance);
                else if (LTestData.Measured_DC_Resistance > 1)
                    sprintf(Temp_String2,"%5.3f Ohms    ",LTestData.Measured_DC_Resistance);
                else
                    sprintf(Temp_String2,"%6.4f Ohms    ",LTestData.Measured_DC_Resistance);
            }
            else {
                sprintf(Temp_String,  "Resistance over ");
                sprintf(Temp_String2, "range, >300 Ohms");
            }
        }
        else if (LTestData.Meas_Action == Measurement_Capacitance){
            if (LTestData.Valid_Capacitance == true){
                sprintf(Temp_String,  "Capacitance:     ");
                if ((LTestData.Measured_Const_I_Cap < Cap_Meas_Lower_Limit)) {
                    sprintf(Temp_String,  "'Cap under range");
                    sprintf(Temp_String2, "< 50nF         ");            
                }
                else 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-3)
                    sprintf(Temp_String2,"%6.1fuF        ", (LTestData.Measured_Const_I_Cap * 1000000));
                else if (LTestData.Measured_Const_I_Cap < 1E-1)
                    sprintf(Temp_String2,"%6.0fuF        ", (LTestData.Measured_Const_I_Cap * 1000000));
                else
                    sprintf(Temp_String2,"%6.5fF         ", (LTestData.Measured_Const_I_Cap));
            }
            else {
                sprintf(Temp_String,  "'Cap under range");
                sprintf(Temp_String2, "< 100nF         ");
            }
        }
        else if (LTestData.Meas_Action == Measurement_Inductance_I){
            if (LTestData.Valid_Const_I_Ind == true){
                sprintf(Temp_String,  "Inductance:     ");
                if (LTestData.Measured_Const_I_Ind < Inductance_Meas_Lower_Limit) {
                    sprintf(Temp_String,  "Ind out of range");
                    sprintf(Temp_String2, "< 50uH, > 4 Ohms");            
                }
                else if (LTestData.Measured_Const_I_Ind < 1E-3)
                    sprintf(Temp_String2,"%3.0fuH   %.3fR ", (LTestData.Measured_Const_I_Ind * 1000000), LTestData.Measured_DC_Resistance);
                else if (LTestData.Measured_Const_I_Ind < 1E-2)
                    sprintf(Temp_String2,"%3.2fmH   %.3fR ", (LTestData.Measured_Const_I_Ind * 1000), LTestData.Measured_DC_Resistance);
                else if (LTestData.Measured_Const_I_Ind < 1E-1)
                    sprintf(Temp_String2,"%4.1fmH  %.3fR ", (LTestData.Measured_Const_I_Ind * 1000), LTestData.Measured_DC_Resistance);
                else
                    sprintf(Temp_String2,"%4.0fmH  %.3fR ", (LTestData.Measured_Const_I_Ind * 1000), LTestData.Measured_DC_Resistance);
            }
            else {
                sprintf(Temp_String,  "Ind out of range");
                sprintf(Temp_String2, "< 50uH, > 4 Ohms");            
            }
        }
        else if (LTestData.Meas_Action == Measurement_Inductance_Sat){
            sprintf(Temp_String,  "Inductance sat  ");
            if (LTestData.DUT_Is_Capacitor)
                sprintf(Temp_String2, "DUT is a cap.   ");
            else if (!LTestData.Valid_DC_Resistance)
                sprintf(Temp_String2, "DUT high res.   ");
            else ;
        }

    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 = false;  // clear flag display for update
    
}

/********************************************************************************/
/*                                                                              */
/* This function assumes there is a resistor connected across the terminals     */
/* 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                                     */
/*                                                                              */
/*          20-0ct-24 added delay to allow inductor current to decay            */
/********************************************************************************/
void handleState_MEASURE_RES() 
{
    float Measured_Resistance;

    /* set sample rate */
    ADC_Sample_Rate(Sample_Rate_Low_Speed);

    /* reset the countdown timer */
    LTestData.Revert_To_Idle_Counter = Revert_To_Idle;
    /* turn current sink off */
    Clear_Test_Current();
    Un_Short_DUT();  // If there is an inductor we want current to decay
    Inductance_Current_Decay_Time;            

    /* 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) {
        Clear_Test_Current();
        Un_Short_DUT();  // If there is an inductor we want current to decay
        Inductance_Current_Decay_Time;            
        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) {
        Clear_Test_Current();
        Un_Short_DUT();  // If there is an inductor we want current to decay
        Inductance_Current_Decay_Time;            
        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) {
        Clear_Test_Current();
        Un_Short_DUT();  // If there is an inductor we want current to decay
        Inductance_Current_Decay_Time;            
        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) {
        Clear_Test_Current();
        Un_Short_DUT();  // If there is an inductor we want current to decay
        Inductance_Current_Decay_Time;            
        Measured_Resistance = Measure_LowLow_Resistance();
        LTestData.Valid_DC_Resistance = true;
        LTestData.Next_Range = false;
    }
    
    LTestData.Measured_DC_Resistance = Measured_Resistance;
    
    /* now back to idle*/
    LTestData.UI_Update_Display = true;  // we need to update the display
    LTestData.state = Inductor_Tester_STATE_IDLE;
}


//******************************************************************************
//
// This 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() 
{
    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();
    /* update the test rail voltage as this matters a lot! */
    Update_Current_Sense_Voltage();   
    /* 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 */
    
    /* 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.2V                                                   */
    /* 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 ((!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.2V                                                   */
    /* C = Delta_T * (LTestData.ISet_CAL_10mA / Cap_Meas_Max_Voltage)   */
    /* Min Cap for 25 counts = 0.3uF                                  */
    /* Max Cap for 12800 counts = 150uF                                  */
    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.2V                                                   */
    /* C = Delta_T * (LTestData.ISet_CAL_10mA / Cap_Meas_Max_Voltage)   */
    /* Min Cap for 25 counts = 3uF                                  */
    /* Max Cap for 12800 counts = 1500uF                                  */
    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.2V                                                   */
    /* C = Delta_T * (LTestData.ISet_CAL_100mA / Cap_Meas_Max_Voltage)   */
    /* Min Cap for 25 counts = 28uf                                         */
    /* Max Cap for 12800 counts = 14700uF                                  */
    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)* (float)LTestData.ISet_CAL_100mA / (float)((float)Cap_Meas_Max_Voltage - (float)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)* (float)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 */
        }    
    }

    /* now back to idle*/
    LTestData.UI_Update_Display = true;  // we need to update the display
    LTestData.state = Inductor_Tester_STATE_IDLE;
}




//******************************************************************************
//
// 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)
// 
// ASSUMPTIONS:
// Assumes that a valid resistance test can be made
// and the resistance is in LTestData.Measured_DC_Resistance
//
//******************************************************************************
void handleState_MEASURE_IND() 
{
    uint16_t *Meas_Ptr = &LTestData.Meas_Buffer[0];
    uint16_t *Meas_Ptr_1 = &LTestData.Meas_Buffer[Half_Meas_Buffer_Size];
    int First_Sample_Meas, Final_Sample_Meas, First_Sample_To_Use, Final_Sample_To_Use = 0;
    float I_Peak, I_Start, I_Average, T_Ramp, V_Test;
    float Inductance_Scale; // This allows us to scale from microhenries to henries
 
   /* init measurements */
    LTestData.Valid_Const_I_Ind = false;        /* start with this as false */
    LTestData.Measured_Const_I_Ind = 0.0;       /* start with this as zero which is error */
    /* update the test rail voltage as this matters a lot! */
    Update_Current_Sense_Voltage();   
    /* reset the countdown timer */
    LTestData.Revert_To_Idle_Counter = Revert_To_Idle;
    /* measure the resistance of the DUT - this is important for corrections*/    
    Clear_Test_Current();
    Un_Short_DUT();  // we want the DUT shorted and the current source to stabilise
    Inductance_Current_Settle;
    handleState_MEASURE_RES();
    
    /* Set inductance Scale to 1.0 to start (microhenries) */
    Inductance_Scale = 1.0;
    /* IF the resistance of the DUT is not too high we can run the test */
    if (LTestData.Measured_DC_Resistance < Inductance_Measurement_Max_Resistance) {
        /* Stage 1 - measure a buffer at high sample rate */
        /* And at a cutoff current of 1A (the system overshoots considerably though  */
        /* there are a few outcomes of this                                          */
        /*  For open circuit, the system will measure a buffer full of over scale    */
        /* for a valid inductor the system will measure a buffer with a pulse from   */
        /*   a low value to full scale, then returning to a low value in the buffer  */
        /* for a short circuit or LOW inductance value the system will go fron low   */
        /*   to full scale then back to low very quickly, or will stay at a low value*/
        /* for an over scale inductor, the system will measure a buffer with a       */
        /*   a pulse from a low value to full scale, then staying high for the buffer*/
        Clear_Test_Current();
        Un_Short_DUT();  // we want the DUT unshorted to allow the current to decay fast
        Inductance_Current_Decay_Time;            
        Short_DUT();  // we want the DUT shorted and the current source to stabilise
        Set_Test_Current(Test_Current_Low_Range);   /* 1A */
        Inductance_Current_Settle;
        Measure_DUT_Voltage_Low_Gain(); /* selects low gain DUT measurement channel */
        Meas_Ptr = &LTestData.Meas_Buffer[0];
        Meas_Ptr_1 = &LTestData.Meas_Buffer[Half_Meas_Buffer_Size];
        /* Select the high gain input (across the 1 Ohm resistor */
        Select_ADC1_Input_To_Read(ADC1_Inductor_Current_High_Gain_Channel_Select);
        /* sample a buffer of values */
        ADC_Ind_Buffer_Capture((int)(Sample_Rate_High_Speed/Inductance_Scale), Meas_Ptr, Meas_Ptr_1);
//        ADC_Ind_Buffer_Capture(Sample_Rate_High_Speed, Meas_Ptr, Meas_Ptr_1);
        /* remove the current */
        Clear_Test_Current();
        Meas_Ptr = &LTestData.Meas_Buffer[0];
        Meas_Ptr_1 = &LTestData.Meas_Buffer[Half_Meas_Buffer_Size];
        ADC_Ind_Buffer_Find_Thresholds(Meas_Ptr, Meas_Ptr_1, &First_Sample_Meas,  &Final_Sample_Meas);
        
        /************************************************/
        /* This bit checks the scale                    */
        /************************************************/
        // 10X scale
        if ((First_Sample_Meas < Half_Meas_Buffer_Size) && (Final_Sample_Meas == Half_Meas_Buffer_Size)) {
            Inductance_Scale = 10.0;
            Clear_Test_Current();
            Un_Short_DUT();  // If there is an inductor we want current to decay
            Inductance_Current_Decay_Time;            
            Short_DUT();  // we want the DUT shorted and the current source to stabilise
            Set_Test_Current(Test_Current_Low_Range);   /* 1A */
            Inductance_Current_Settle;
            Measure_DUT_Voltage_Low_Gain(); /* selects low gain DUT measurement channel */
            Meas_Ptr = &LTestData.Meas_Buffer[0];
            Meas_Ptr_1 = &LTestData.Meas_Buffer[Half_Meas_Buffer_Size];
            /* Select the high gain input (across the 1 Ohm resistor */
            Select_ADC1_Input_To_Read(ADC1_Inductor_Current_High_Gain_Channel_Select);
            /* sample a buffer of values */
            ADC_Ind_Buffer_Capture((int)(Sample_Rate_High_Speed/Inductance_Scale), Meas_Ptr, Meas_Ptr_1);
            /* remove the current */
            Clear_Test_Current();  // get rid of test current ASAP
            Meas_Ptr = &LTestData.Meas_Buffer[0];
            Meas_Ptr_1 = &LTestData.Meas_Buffer[Half_Meas_Buffer_Size];
            ADC_Ind_Buffer_Find_Thresholds(Meas_Ptr, Meas_Ptr_1, &First_Sample_Meas,  &Final_Sample_Meas);
        }
        // 100X scale
        if ((First_Sample_Meas < Half_Meas_Buffer_Size) && (Final_Sample_Meas == Half_Meas_Buffer_Size)) {
            Inductance_Scale = 100.0;
            Clear_Test_Current();
            /* now try the DUT Unsorted for a bit */
            Un_Short_DUT();  // we want the DUT shorted and the current source to stabilise
            Inductance_Current_Decay_Time;            
            Short_DUT();  // we want the DUT shorted and the current source to stabilise
            Set_Test_Current(Test_Current_Low_Range);   /* 1A */
            Inductance_Current_Settle;
            Measure_DUT_Voltage_Low_Gain(); /* selects low gain DUT measurement channel */
            Meas_Ptr = &LTestData.Meas_Buffer[0];
            Meas_Ptr_1 = &LTestData.Meas_Buffer[Half_Meas_Buffer_Size];
            /* Select the high gain input (across the 1 Ohm resistor */
            Select_ADC1_Input_To_Read(ADC1_Inductor_Current_High_Gain_Channel_Select);
            /* sample a buffer of values */
            ADC_Ind_Buffer_Capture((int)(Sample_Rate_High_Speed/Inductance_Scale), Meas_Ptr, Meas_Ptr_1);
            /* remove the current */
            Clear_Test_Current();  // get rid of test current ASAP
            Meas_Ptr = &LTestData.Meas_Buffer[0];
            Meas_Ptr_1 = &LTestData.Meas_Buffer[Half_Meas_Buffer_Size];
            ADC_Ind_Buffer_Find_Thresholds(Meas_Ptr, Meas_Ptr_1, &First_Sample_Meas,  &Final_Sample_Meas);
        }
        // 1000X scale
        if ((First_Sample_Meas < Half_Meas_Buffer_Size) && (Final_Sample_Meas == Half_Meas_Buffer_Size)) {
            Inductance_Scale = 1000.0;
            Clear_Test_Current();
            /* now try the DUT Unsorted for a bit */
            Un_Short_DUT();  // we want the DUT shorted and the current source to stabilise
            Inductance_Current_Decay_Time;            
            Short_DUT();  // we want the DUT shorted and the current source to stabilise
            Set_Test_Current(Test_Current_Low_Range);   /* 1A */
            Inductance_Current_Settle;
            Measure_DUT_Voltage_Low_Gain(); /* selects low gain DUT measurement channel */
            Meas_Ptr = &LTestData.Meas_Buffer[0];
            Meas_Ptr_1 = &LTestData.Meas_Buffer[Half_Meas_Buffer_Size];
            /* Select the high gain input (across the 1 Ohm resistor */
            Select_ADC1_Input_To_Read(ADC1_Inductor_Current_High_Gain_Channel_Select);
            /* sample a buffer of values */
            ADC_Ind_Buffer_Capture((int)(Sample_Rate_High_Speed/Inductance_Scale), Meas_Ptr, Meas_Ptr_1);
            /* remove the current */
            Clear_Test_Current();  // get rid of test current ASAP
            Meas_Ptr = &LTestData.Meas_Buffer[0];
            Meas_Ptr_1 = &LTestData.Meas_Buffer[Half_Meas_Buffer_Size];
            ADC_Ind_Buffer_Find_Thresholds(Meas_Ptr, Meas_Ptr_1, &First_Sample_Meas,  &Final_Sample_Meas);
        }
        /* If there is a valid start and end then lets calculate the inductance */
        /* Else this is not a valid inductor                                    */
        if((First_Sample_Meas == Half_Meas_Buffer_Size) && (Final_Sample_Meas == Half_Meas_Buffer_Size)) {
            LTestData.Valid_Const_I_Ind = false;        /* both these being zero means no pulse was found so under range */
            LTestData.Measured_Const_I_Ind = 0.0;       /* start with this as zero which is error */
        }
        /* OK so we now have a buffer we like the looks of with valid data in it and a "range" setting */
        /* This will be a valid measurement */
        else {
            /* use the middle section of the data buffer to avoid the start and end of ramp */
            Final_Sample_To_Use = First_Sample_Meas + ((Final_Sample_Meas - First_Sample_Meas) * Inductance_Measurement_ConstI_Buffer_End_Ratio);
            First_Sample_To_Use = First_Sample_Meas + ((Final_Sample_Meas - First_Sample_Meas) * Inductance_Measurement_ConstI_Buffer_Start_Ratio);
            /* we need to work out di/dt */
            I_Start = LTestData.Meas_Buffer[Half_Meas_Buffer_Size + First_Sample_To_Use];
            I_Peak = LTestData.Meas_Buffer[Half_Meas_Buffer_Size + Final_Sample_To_Use];
            //    I_Peak = I_Peak * Current_Scaling_From_Low_Gain_ADC;
            I_Peak = I_Peak * Current_Scaling_From_High_Gain_ADC;
            I_Start = I_Start * Current_Scaling_From_High_Gain_ADC;
            /* the current curve is pretty linear... */
            I_Average = (I_Start + I_Peak)/2;
            /* this is the dt... */
            T_Ramp = (float)((Final_Sample_To_Use - First_Sample_To_Use) * Inductance_Scale)/Sample_Rate_High_Speed;
            /* the actual voltage the inductor sees is Itest ( the load resistance plus DUT resistance) */
            /* remember if the VA rail of the PIC changes this will mess up the ADC full scale - you pillock */
            V_Test = LTestData.Test_Rail_V_Meas; 
            V_Test = V_Test - (I_Average * (Current_Sense_Resistance_High_Gain + LTestData.Measured_DC_Resistance));
            /* and this is the simple sum to calculate the inductance... */
            LTestData.Measured_Const_I_Ind = V_Test/((I_Peak - I_Start)/T_Ramp);
            LTestData.Valid_Const_I_Ind = true;
        }

    }  //
    else {
        LTestData.Valid_Const_I_Ind = false;
    }
    /* tidy up after yourself */    
    Un_Short_DUT();
    /* now back to idle*/
    LTestData.state = Inductor_Tester_STATE_IDLE;
    LTestData.UI_Update_Display = true;  // we need to update the display
}


//******************************************************************************
//
// Assume there is an inductor across the terminals
// And that we have a valid measurement of:
//  Inductance
//  Resistance
//
// This allows us to determine 
//      1. The maximum current we will subject it to (DC resistance limit)
//      2. About how long to let things go before we stop!
//      3. The automatic cutoff current
//
//******************************************************************************
void handleState_MEASURE_IND_SAT()
{
    char Temp_String[20],Temp_String2[20];
    float Peak_Test_Current;
    float di_dt_Estimate;
    float Test_Duration_Estimate;
    long int Required_Sample_Rate;
    uint16_t *Meas_Ptr = &LTestData.Meas_Buffer[0];   // current starts here
    uint16_t *Meas_Ptr_1 = &LTestData.Meas_Buffer[Half_Meas_Buffer_Size];   // test voltage starts here
    int First_Sample_Meas, Final_Sample_Meas;
    int Samples_per_Inductance_Step;
    float Drive_V;
    float Delta_I;
    float Delta_T;
    int i, j;
    int T_Steps;
//    int Inductance_Step_No;
//    float Inductance_At_Step;
    
            
    Measure_Test_Voltage_Rail(); /* selects ADCO to measure the test rail voltage */
    Select_ADC1_Input_To_Read(ADC1_Inductor_Current_Channel_Select);   // monitor inductor current
    /* read the rail sense */
    Measure_Test_Voltage_Rail();
    /* now lets look at the test rail voltage */
    CORETIMER_DelayMs(Inductance_Measurement_Rail_Meas_Settle);
    LTestData.Test_Rail_V_Meas = (ADC0_Low_Gain()/(Test_Rail_Voltage_Scaling));
    /* now make sure we have the right resistance and inductance */
    handleState_MEASURE_IND();
    /* start with no valid answer */
    LTestData.Valid_Sat_I = false;
    /* set the sample rate high */
    ADC_Sample_Rate(Sample_Rate_High_Speed);
    /* start with assumption the DUT is not a Capacitor */
    LTestData.DUT_Is_Capacitor = false;

   /***************************************************************************/ 
   /* Is this really an inductor?                                             */
   /***************************************************************************/ 
    if (LTestData.Valid_DC_Resistance) { 
//    LTestData.DUT_Is_Capacitor = DUT_Is_A_Capacitor();
    do {
        /* now make sure we have the right resistance and inductance */
        handleState_MEASURE_IND();
        LTestData.DUT_Is_Capacitor = DUT_Is_A_Capacitor();
        
        if(!LTestData.DUT_Is_Capacitor) {
            
            /* turn on constant current source to generate a small bias that puts the */
            /* current sense IC into its linear operating region */
            Set_Test_Current(Const_Current_Source_Bias_Current); 
            /* select measurement channel */
            Select_ADC0_Input_To_Read(ADC0_Voltage_Sense_Channel_Select);  // watch the voltage rails
            Select_ADC1_Input_To_Read(ADC1_Inductor_Current_Channel_Select);   // monitor inductor current
            /* Peak Test Current is notionally 50% of R/R limit */
            Initialise_Pulser();  /* want this to be cleared */

            Peak_Test_Current = LTestData.Test_Rail_V_Meas / LTestData.Measured_DC_Resistance * Peak_Test_Current_of_V_R;
            if (Peak_Test_Current > Max_Test_Current)
                Peak_Test_Current = Max_Test_Current;
            Initialise_Pulser();  /* want this to be cleared */
            /* OK how long will it take for the current to build to the limit? */
            di_dt_Estimate = LTestData.Test_Rail_V_Meas / LTestData.Measured_Const_I_Ind;
            Test_Duration_Estimate = Peak_Test_Current/di_dt_Estimate;
            /* oversize the initisl buffer - high resistance High Isat inductors need this */
            Test_Duration_Estimate = Test_Duration_Estimate * Capture_Buffer_Oversize;
            /* now set sample rate to grab the full buffer */
            /* Num_DMA_Buffers_LTest is the buffer size */
            Required_Sample_Rate = (long int) (Half_Meas_Buffer_Size / Test_Duration_Estimate);
            if (Required_Sample_Rate > Sample_Rate_High_Speed)
                Required_Sample_Rate = Sample_Rate_High_Speed;
            /* now grab the data */
            ADC_Ind_Sat_Buffer_Capture(Peak_Test_Current, Required_Sample_Rate, Meas_Ptr, Meas_Ptr_1);
            // then look inside this for where the Icutoff REALLY is
            ADC_Ind_Sat_Buffer_Find_Thresholds(Peak_Test_Current, Meas_Ptr, Meas_Ptr_1, &First_Sample_Meas, &Final_Sample_Meas);

            /***************************************************************/
            /*  Now lets reset the measurement time - add 20%              */
            /***************************************************************/
            Test_Duration_Estimate = 1.2* Final_Sample_Meas / Required_Sample_Rate;
            /* now re set sample rate to grab the full buffer */
            Required_Sample_Rate = (long int) ((float)Half_Meas_Buffer_Size / (float)Test_Duration_Estimate);
            if (Required_Sample_Rate > Sample_Rate_High_Speed)
                Required_Sample_Rate = Sample_Rate_High_Speed;
            /* now grab the data after a brief delay */
            Time_For_PSU_To_Settle;
            ADC_Ind_Sat_Buffer_Capture(Peak_Test_Current, Required_Sample_Rate, Meas_Ptr, Meas_Ptr_1);
            // then look inside this for where the Icutoff REALLY is
            ADC_Ind_Sat_Buffer_Find_Thresholds(Peak_Test_Current, Meas_Ptr, Meas_Ptr_1, &First_Sample_Meas, &Final_Sample_Meas);
            /* now turn the test current off */
            Clear_Test_Current();
             
            // and pull the results from this
            for(i=0; i< Num_Sat_Samples; i++) {
                T_Steps = (Final_Sample_Meas - First_Sample_Meas)/Num_Sat_Samples;
                // calculate the current
                LTestData.Measured_Sat_Current_Results[0][i] = 0;
                Delta_I = 0; // reset this
                /* Delta current  -average 4 pulses around this*/
                /* average current across the period */
                for (j=0; j < 3; j++) {
                    Delta_I += LTestData.Meas_Buffer[First_Sample_Meas + Half_Meas_Buffer_Size + ((i+1)*T_Steps) + j-1];
                    Delta_I -= LTestData.Meas_Buffer[First_Sample_Meas + Half_Meas_Buffer_Size + (i*    T_Steps) + j-1];
                    LTestData.Measured_Sat_Current_Results[0][i] += (float)(LTestData.Meas_Buffer[First_Sample_Meas + Half_Meas_Buffer_Size + (i*     T_Steps) + j-1]);
                    LTestData.Measured_Sat_Current_Results[0][i] += (float)(LTestData.Meas_Buffer[First_Sample_Meas + Half_Meas_Buffer_Size + ((i+1) *T_Steps) + j-1]);
                }
                Delta_I *=(float)ADC_To_Amps_Sat/(3 * High_Gain_Current_Scale);
                LTestData.Measured_Sat_Current_Results[0][i] /= 6;
                LTestData.Measured_Sat_Current_Results[0][i] *=(float)ADC_To_Amps_Sat/(float)High_Gain_Current_Scale;

                /* now the average voltage */
                Drive_V = 0; // reset this
                for (j=0; j < T_Steps; j++) {
                    Drive_V += (float)LTestData.ADC_Full_Scale_V*(float)(LTestData.Meas_Buffer[First_Sample_Meas + (i*T_Steps) + j]);
                }
                Drive_V /= (float)((float)Test_Rail_Voltage_Scaling * (float)ADC_MAX_COUNT  * (float)T_Steps);
                Drive_V = Drive_V - LTestData.Measured_DC_Resistance* LTestData.Measured_Sat_Current_Results[0][i];

                /* calculate time*/
//                Delta_T = (float)T_Steps / (float)Required_Sample_Rate;
                Delta_T = (float)T_Steps * (float)(TMR3_PeriodGet() + 2) / 120000000;                
                

                LTestData.Measured_Sat_Current_Results[1][i] = Drive_V * Delta_T/Delta_I;
//                sprintf(Temp_String,"I:%4.1fA R:%4.3f", LTestData.Measured_Sat_Current_Results[0][i], LTestData.Measured_DC_Resistance);            
                sprintf(Temp_String,"I:%4.1fA R:%4.3f", LTestData.Measured_Sat_Current_Results[0][i], (float)LTestData.ADC_Full_Scale_V*(float)(LTestData.Meas_Buffer[First_Sample_Meas + (i*T_Steps)])/((float)Test_Rail_Voltage_Scaling * (float)ADC_MAX_COUNT ));            
//                sprintf(Temp_String,"V:%4.3fV R:%4.3f", Drive_V, Delta_I/Delta_T);            
//                sprintf(Temp_String2,"%5.3fmH %2i", LTestData.Measured_Sat_Current_Results[1][i] * 1000,(i+1));
                sprintf(Temp_String2,"%5.3fmH %3.3f", LTestData.Measured_Sat_Current_Results[1][i] * 1000,Delta_T*1000);
//                sprintf(Temp_String2,"%1.2f %4.3f mH", LTestData.Measured_Sat_Current_Results[0][i] , LTestData.Measured_Sat_Current_Results[1][i] * 1000);
                LCD_TextOut(1,0,(unsigned char *)Temp_String2);
                LCD_TextOut(0,0,(unsigned char *)Temp_String);
                CORETIMER_DelayMs(3000);

            }        
            
            if((First_Sample_Meas == Final_Sample_Meas) || (Final_Sample_Meas == Half_Meas_Buffer_Size)){
                sprintf(Temp_String, "Saturation Test "); 
                sprintf(Temp_String2, "Invalid Data    "); 
                LCD_TextOut(1,0,(unsigned char *)Temp_String2);
                LCD_TextOut(0,0,(unsigned char *)Temp_String);                
            }
            else {              // valid device and measurements
                sprintf(Temp_String, "F %i L%i ", First_Sample_Meas, Final_Sample_Meas); 
                sprintf(Temp_String2,"I%4.1f M%4.1f ", (float)LTestData.Meas_Buffer[First_Sample_Meas + Half_Meas_Buffer_Size]*ADC_To_Amps_Sat, (float)LTestData.Meas_Buffer[Final_Sample_Meas + Half_Meas_Buffer_Size]*ADC_To_Amps_Sat);
                LCD_TextOut(1,0,(unsigned char *)Temp_String2);
                LCD_TextOut(0,0,(unsigned char *)Temp_String);
                CORETIMER_DelayMs(1000);

                Samples_per_Inductance_Step = (Final_Sample_Meas - First_Sample_Meas)/10;
                Drive_V = LTestData.ADC_Full_Scale_V*((float)LTestData.Meas_Buffer[Final_Sample_Meas] + (float)LTestData.Meas_Buffer[First_Sample_Meas])/(2 * Test_Rail_Voltage_Scaling * ADC_MAX_COUNT);
                Delta_I = (float)LTestData.Meas_Buffer[First_Sample_Meas + Half_Meas_Buffer_Size + Samples_per_Inductance_Step]*ADC_To_Amps_Sat - (float)LTestData.Meas_Buffer[First_Sample_Meas + Half_Meas_Buffer_Size]*ADC_To_Amps_Sat;

                sprintf(Temp_String, "V%4.3f I%4.1f ", Drive_V, Delta_I); 
                sprintf(Temp_String2,"I%4.1f M%4.1f ", (float)LTestData.Meas_Buffer[First_Sample_Meas + Half_Meas_Buffer_Size]*ADC_To_Amps_Sat, (float)LTestData.Meas_Buffer[Final_Sample_Meas + Half_Meas_Buffer_Size]*ADC_To_Amps_Sat);
                LCD_TextOut(1,0,(unsigned char *)Temp_String2);
                LCD_TextOut(0,0,(unsigned char *)Temp_String);
                CORETIMER_DelayMs(1000);
            }
        }
        else {
            sprintf(Temp_String, "DUT is          "); 
            sprintf(Temp_String2, "capacitor!!!!   "); 
            LCD_TextOut(1,0,(unsigned char *)Temp_String2);
            LCD_TextOut(0,0,(unsigned char *)Temp_String);
        };
        
                 
    } while (1);
        
        

        
     //    Resistive_Current_Limit = LTestData.Measured_DC_Resistance / LTestData.Test_Rail_V_Meas;

         do{
                 Set_Cutoff_Current(20);
                 Initialise_Pulser();

               CORETIMER_DelayUs(Pulser_Time);
               Pulse_Start();
                 CORETIMER_DelayMs(100);
         sprintf(Temp_String, "In Sat Test     "); 
         sprintf(Temp_String2,"Check D output  ");
         LCD_TextOut(1,0,(unsigned char *)Temp_String2); 
         LCD_TextOut(0,0,(unsigned char *)Temp_String);
         } 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() 
{
    /* 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();

    if (LTestData.UI_Update_Display == true) {
        Display_Results();
        LTestData.UI_Update_Display = false;
    }
    
       /* 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) && (!Enter_Key_Pressed));
    
    if ((Up) || (Down)) {     
        if (Down) {
            LTestData.Meas_Action--;
            if (LTestData.Meas_Action < Measurement_Resistance)
                LTestData.Meas_Action = Measurement_Inductance_Sat;
        }
        else if (Up) {
            LTestData.Meas_Action++;
            if (LTestData.Meas_Action > Measurement_Inductance_Sat)
                LTestData.Meas_Action = Measurement_Resistance;
        }      
        Idle_Screen();   /* display what the user is asking to be done */
    }
    else if (Enter_Key_Pressed) { //not Exit_Key_Pressed
        if (LTestData.Meas_Action == Measurement_Resistance){
            LTestData.state = Inductor_Tester_STATE_MEASURE_RES;
        }
        else if (LTestData.Meas_Action == Measurement_Capacitance){
            LTestData.state = Inductor_Tester_STATE_MEASURE_CAP;
        }
        else if (LTestData.Meas_Action == Measurement_Inductance_I){
            LTestData.state = Inductor_Tester_STATE_MEASURE_IND;
        }
        else if (LTestData.Meas_Action == Measurement_Inductance_Sat){
            LTestData.state = Inductor_Tester_STATE_MEASURE_IND_SAT;
        }  
        
        Acting_On_Idle_Screen();   /* display what the user is asking to be done */
        
    }
    else {
        LTestData.state = Inductor_Tester_STATE_IDLE;
        Idle_Screen();
    }
}



// *****************************************************************************
// *****************************************************************************
// 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;         
        case Inductor_Tester_STATE_MEASURE_IND_SAT:
            handleState_MEASURE_IND_SAT();
            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
*/

