//###########################################################################
//
// FILE:    misc.c
//
// TITLE:
//
// NOTES:
//  1)
//###########################################################################
//
//  Ver  | dd mmm yyyy | Who  		| Description of changes
// ======|=============|============|========================================
//  00 	   05 04 2015 	 HPCS
//
//  Texas Instruments, Inc
//  Copyright Texas Instruments 2008. All rights reserved.
//###########################################################################
#include "system_defines.h"
#include "cyclone_device.h"
#include "variables.h"
#include "function_definitions.h"
#include "software_interrupts.h"
#include "cyclone_defines.h"
#include "pmbus_common.h"
#include "pmbus_topology.h"
#include "pmbus_constants.h"

void delay()
{
	volatile int i,j;
	for(i=0;i<100000;i++)
	{
		i++;
		pmbus_handler();
		poll_adc();
	}

}


void set_board_mode(void)
{
	if(dflash_variables.variables.board_mode == 1)
	{
			test();
	}
	if(dflash_variables.variables.board_mode == 2)
	{

		for(;;)
		{
//		if ((current_reading_error[25] != 0) &&  dflash_variables.variables.calibrate_state ==1000)
//				{
//					 dflash_variables.variables.calibrate_state=0;
//				}
			pmbus_handler();
			fine_tune();
			poll_adc();
			calibrate();


//			if (store == 1000)
//			{
//				store =0;
//				 dflash_variables.variables.calibrate_state=14;
//			}
		}

	}
}
void check_need_for_clearing_checksum(void)
{
	Uint32 main_counter;
	if (adc_struct.system_voltage_avg_32  < ( (ADC_VALUE_FOR_12V)/2 ) )
	{
		main_counter=0;

		while (adc_struct.system_voltage_avg_32  < ( (ADC_VALUE_FOR_12V*3)/4 ))
		{

			poll_adc();
			if(main_counter < 1000000)
			{
				main_counter++;
			}
			else
			{
				break;
			}
		}
		if(main_counter < 1000000)
		{
			clear_integrity_word();
		}
}
}



void calculate_values()
{
float temp ;
Uint32 i;
static Uint32 got_25;

	if (wait_done ==1)
	{


		battery_voltage=(float)(adc_struct.battery_voltage_avg_32 * NOMINAL_BATTERY_VOLTAGE)
							/ dflash_variables.variables.ADC_Value_for_nominal_battery_voltage;
		system_voltage=(float)(adc_struct.system_voltage_avg_32 *NOMINAL_SYSTEM_VOLTAGE)
							/ dflash_variables.variables.ADC_Value_for_nominal_system_voltage;




		Discharge_Ratio = (Uint32)((0x7FFFFF ) * DPWM2_FIXED_DUTY);
		Discharge_Ratio = (Uint32)((battery_voltage * Discharge_Ratio )/system_voltage );


			temp =(float)adc_struct.temp_reading/(float)1638;
			Inductor_temperature = (1.8639 - temp) * 85.47;

			index =(battery_voltage*10 - 130);
			if(index > 45)
			{
				index =45;
			}
			if(index < 0 )
			{
				index =0;
			}

			i= (int)Inductor_temperature;
			if (25  == (int)Inductor_temperature )
			{
				got_25=1;
				current_reading_error[25]= adc_struct.Current_sum;
			}

			if ((got_25 ==1) && (i!=25))
			{

			current_reading_error[i]= 	adc_struct.Current_sum-current_reading_error[25] ;
			}

	}
}

void update_current_limit()
{



	FaultMuxRegs.DCOMPCTRL1.bit.THRESH =dflash_variables.variables.current_readings[index].CCM_zero_current_EADC_ABS_reading;
	current_ref_value=dflash_variables.variables.current_readings[index].DCM_1A_charging_ref;

}

void check_for_errors()
{
	static int local_state=0;

	switch (local_state)
	{

	case 0:
		if( FaultMuxRegs.FAULTMUXINTSTAT.bit.ACOMP_F == 1)
					{
						error_state=OVER_BATTERY_VOLTAGE;
						converter_state=PS_OFF;
						mini_state_during_error=mini_state;
						error_value=adc_struct.battery_voltage_avg_32;
						local_state=100;
					}
		break;
	case 1:
		    if( FaultMuxRegs.FAULTMUXINTSTAT.bit.ACOMP_A == 1)
				{
					error_state=OVER_SYSTEM_SUPPLY_VOLTAGE;
					converter_state=PS_OFF;
					mini_state_during_error=mini_state;
					error_value=adc_struct.system_voltage_avg_32;
					local_state=100;
				}
		break;
	case 2:
			if(adc_struct.battery_voltage_avg_32 < dflash_variables.variables.UVP_battery)
				{
					converter_state=PS_OFF;
					mini_state_during_error=mini_state;
					error_state=UNDER_BATTERY_VOLTAGE;
					error_value=adc_struct.battery_voltage_avg_32;
					local_state=100;
				}
			break;
	case 3:
		//
		//			else if( FaultMuxRegs.FAULTMUXINTSTAT.bit.DCOMP1 == 1)
		//			{
		//				error_state=BATTERY_OVER_CURRENT;
		//				converter_state=ERROR;
		//				error_value=AdcRegs.ADCRESULT[2].all + AdcRegs.ADCRESULT[3].all ;
		//			}


		break;
	case 4:
		break;
	case 100:
		if (error_state !=NO_ERROR )
		{
		local_state--;
		}
		break;
	default :
		local_state=-1;
		break;
	}
	local_state++;
}

int wait_for_steady_state(Uint32 ADC_reading)
{

	static int count=0;

	static Uint32 steady_voltage_counter=0;
	static int previous_ADC_reading;

	switch(wait_for_steady_state_machine)
	{
		case 0:
			count++;
			if(count ==100000)
			{
			count=0;
			wait_for_steady_state_machine=1;
			previous_ADC_reading =ADC_reading ;
			}
			break;
		case 1:

			count++;

			if (count == 1000)
			{
				count=0;
				if (abs(ADC_reading - previous_ADC_reading) < 3 )
				{
					steady_voltage_counter++;
				}
				else
				{
					   previous_ADC_reading = ADC_reading;
					   steady_voltage_counter=0;
				}
			}

			if (100 == steady_voltage_counter)
			{
				wait_for_steady_state_machine=2;
				steady_voltage_counter=0;
				previous_ADC_reading =ADC_reading ;
				return 1;
			}
			break;
		case 2:
			if ( abs( previous_ADC_reading  - ADC_reading) > 10 )
			{
				wait_for_steady_state_machine=0;
			}
			break;

	}

	return 0;
}
Uint16 get_EADC_DAC_Value_for_zero_error()
{

Uint16 temp_value;

            MiscAnalogRegs.GLBIOVAL.bit.DPWM0A_IO_VALUE=0;
            MiscAnalogRegs.GLBIOVAL.bit.DPWM0B_IO_VALUE=0;
            MiscAnalogRegs.GLBIOOE.bit.DPWM0A_IO_OE=1;
            MiscAnalogRegs.GLBIOOE.bit.DPWM0B_IO_OE=1;
            MiscAnalogRegs.GLBIOEN.bit.DPWM0A_IO_EN=1;
            MiscAnalogRegs.GLBIOEN.bit.DPWM0B_IO_EN=1;


            Dpwm0Regs.DPWMCTRL0.bit.PWM_EN = 0;     //disable locally for init
            Dpwm0Regs.DPWMCTRL0.bit.CLA_EN = 0;     //default is 1 - use cla

            Dpwm0Regs.DPWMCTRL0.bit.PWM_MODE = 0; //normal mode
            Dpwm0Regs.DPWMPRD.all = DPWM_PERIOD;         //use .all for all values, make sure scaling matches.
            Dpwm0Regs.DPWMEV1.all = (DEAD_TIME_1)+10;              //Put event 1 at start of period
            Dpwm0Regs.DPWMEV2.all =((DPWM_PERIOD)>>5);       //1/4 of period - divide is OK because it's all constants.
            Dpwm0Regs.DPWMEV3.all = ((DPWM_PERIOD)>>5)+(DEAD_TIME_2);       //1/2 of period
            Dpwm0Regs.DPWMEV4.all = 10;
            Dpwm0Regs.DPWMSAMPTRIG1.all =2000 ;

            Dpwm0Regs.DPWMCTRL2.bit.SAMPLE_TRIG_1_EN = 1; //enable 1 sample trigger
            Dpwm0Regs.DPWMCTRL1.bit.EVENT_UP_SEL = 1; //update at end of period

            Dpwm0Regs.DPWMPHASETRIG.all=(DPWM_PERIOD)/4;

            FeCtrl0Regs.EADCCTRL.bit.AFE_GAIN = 3;// Gain X8
            FeCtrl0Regs.EADCCTRL.bit.EADC_MODE = 0;
            FeCtrl0Regs.RAMPCTRL.bit.RAMP_EN = 1;
            FeCtrl0Regs.EADCCTRL.bit.SAMP_TRIG_SCALE= 0;
            FeCtrl0Regs.EADCCTRL.bit.EADC_ENA = 1;

            LoopMuxRegs.SAMPTRIGCTRL.bit.FE0_TRIG_DPWM0_EN = 1;  // Enables Sample Trigger from DPWM 0 to Front End Control 0
            LoopMuxRegs.GLBEN.bit.DPWM0_EN=1;
            LoopMuxRegs.GLBEN.bit.FE_CTRL0_EN=1;
            Dpwm0Regs.DPWMCTRL0.bit.PWM_EN = 1;

            while(FeCtrl0Regs.EADCVALUE.bit.ERROR_VALUE !=0)
            {
                pmbus_handler();
                fine_tune();
                if( FeCtrl0Regs.EADCVALUE.bit.ERROR_VALUE <0)
                {
                    FeCtrl0Regs.EADCDAC.bit.DAC_VALUE++;
                }
                else if(FeCtrl0Regs.EADCVALUE.bit.ERROR_VALUE >0)
                {
                    FeCtrl0Regs.EADCDAC.bit.DAC_VALUE--;
                }
                error_state=CALIBRATION_ERROR;
            }
            temp_value = FeCtrl0Regs.EADCDAC.bit.DAC_VALUE;

            return temp_value;
}

void read_EADC()
{

	volatile int j;
	int i;



			FeCtrl0Regs.EADCDAC.bit.DAC_VALUE= 0;


			for(i=0;i<400000;i++)
			{
			j++;
			}

			{
			I_OUT_ZERO=	I_OUT_ZERO- ( (FeCtrl0Regs.EADCVALUE.bit.ERROR_VALUE)*(10.24) );
			}

			FeCtrl0Regs.EADCDAC.bit.DAC_VALUE= I_OUT_ZERO;

			while(FeCtrl0Regs.EADCVALUE.bit.ERROR_VALUE !=0)
			{
				pmbus_handler();
				fine_tune();
				if( FeCtrl0Regs.EADCVALUE.bit.ERROR_VALUE <2)
				{
					FeCtrl0Regs.EADCDAC.bit.DAC_VALUE++;
				}
				else if(FeCtrl0Regs.EADCVALUE.bit.ERROR_VALUE >2)
				{
					FeCtrl0Regs.EADCDAC.bit.DAC_VALUE--;
				}

			}
			I_OUT_ZERO=FeCtrl0Regs.EADCDAC.bit.DAC_VALUE;
}
void calibrate()
{

static Uint32 count=0;
static int previous_index;
static Uint32 CCM_15V_current;

converter_state=CALIBRATING;

calculate_values();


	switch(dflash_variables.variables.calibrate_state)
	{
	case CAPTURE_SYSTEM_OVP:
	         //   if(wait_for_steady_state(adc_struct.system_voltage_avg_32))
	            {
	                dflash_variables.variables.OVP_system=adc_struct.system_voltage_avg_32;
	               // delay();
	                dflash_variables.variables.calibrate_state=CAPTURE_NOTHING;
	            }
	        break;
	case CAPTURE_BATTERY_OVP:
			//if(wait_for_steady_state(adc_struct.battery_voltage_avg_32))
			{
				dflash_variables.variables.OVP_battery=adc_struct.battery_voltage_avg_32;
				// delay();
				                    dflash_variables.variables.calibrate_state=CAPTURE_NOTHING;
			}
		break;
	case CAPTURE_CC_to_CV:
		//if(wait_for_steady_state(adc_struct.battery_voltage_avg_32))
				{
					dflash_variables.variables.ADC_Value_for_CCtoCV_switch_ON_BATT_SIDE=adc_struct.battery_voltage_avg_32;
					// delay();
					                    dflash_variables.variables.calibrate_state=CAPTURE_NOTHING;
				}
		break;
	case CAPTURE_BATTERY_NOM:
		//if(wait_for_steady_state(adc_struct.battery_voltage_avg_32))
			{
				dflash_variables.variables.ADC_Value_for_nominal_battery_voltage=adc_struct.battery_voltage_avg_32;
				// delay();
				                    dflash_variables.variables.calibrate_state=CAPTURE_NOTHING;
			}
		break;
	case CAPTURE_SYSTEM_NOM:
		//if(wait_for_steady_state(adc_struct.system_voltage_avg_32))
            {
                dflash_variables.variables.ADC_Value_for_nominal_system_voltage=adc_struct.system_voltage_avg_32;
                // delay();
                                    dflash_variables.variables.calibrate_state=CAPTURE_NOTHING;
            }
		break;
	case CAPTURE_SYSTEM_UVP:
		//if(wait_for_steady_state(adc_struct.system_voltage_avg_32))
            {
                dflash_variables.variables.ADC_Value_for_trigger_point_ON_PS_SIDE=adc_struct.system_voltage_avg_32;
                dflash_variables.variables.UVP_system=dflash_variables.variables.ADC_Value_for_trigger_point_ON_PS_SIDE;
                // delay();
                                    dflash_variables.variables.calibrate_state=CAPTURE_NOTHING;
            }
		break;
	case CAPTURE_BATTERY_UVP:
		//if(wait_for_steady_state(adc_struct.battery_voltage_avg_32))
				{
					dflash_variables.variables.UVP_battery=adc_struct.battery_voltage_avg_32;
					// delay();
					                    dflash_variables.variables.calibrate_state=CAPTURE_NOTHING;

				}
				break;
	case CAPTURE_DAC_CC:
	{
	    dflash_variables.variables.EADC_DAC_value_for_constant_current= get_EADC_DAC_Value_for_zero_error();
	    dflash_variables.variables.ADC_value_for_constant_current_charging=adc_struct.battery_current;
	       dflash_variables.variables.calibrate_state=CAPTURE_NOTHING;
	}
    break;
    case CAPTURE_BATTERY_OCP:
    {

        dflash_variables.variables.OCP_battery=adc_struct.battery_current;
           dflash_variables.variables.calibrate_state=CAPTURE_NOTHING;
    }
    break;
    case CAPTURE_SYSTEM_OCP:
      {

          dflash_variables.variables.OCP_system=adc_struct.system_current;
             dflash_variables.variables.calibrate_state=CAPTURE_NOTHING;
      }

      break;
		case CAPTURE_NOTHING:
			break;
		default:
		    break;


	}//switch
}//function


void restore_defaults()
{

	D_T1=DEAD_TIME_1;
	D_T2=DEAD_TIME_2;
	error_state=NO_ERROR;
}

void fine_tune(void)
{
volatile Uint32 return_value;

	if(store == 3)
		{
		return_value =store_to_DFLASH_slow();
			if (1 == return_value)
			{
				store=0;
			}
		}
}

/*
 * This function senses the output current when no DPWM's are running and provides a
 * EADC DAC reference i.e I_OUT_ZERO
 */
void initial_setup()
{
		volatile Uint32 i,j;
		volatile int32 delta,temp;


		MiscAnalogRegs.GLBIOVAL.bit.DPWM0A_IO_VALUE=0;
		MiscAnalogRegs.GLBIOVAL.bit.DPWM0B_IO_VALUE=0;
		MiscAnalogRegs.GLBIOOE.bit.DPWM0A_IO_OE=1;
		MiscAnalogRegs.GLBIOOE.bit.DPWM0B_IO_OE=1;
		MiscAnalogRegs.GLBIOEN.bit.DPWM0A_IO_EN=1;
		MiscAnalogRegs.GLBIOEN.bit.DPWM0B_IO_EN=1;


		Dpwm0Regs.DPWMCTRL0.bit.PWM_EN = 0;     //disable locally for init
		Dpwm0Regs.DPWMCTRL0.bit.CLA_EN = 0;		//default is 1 - use cla

		Dpwm0Regs.DPWMCTRL0.bit.PWM_MODE = 0; //normal mode
		Dpwm0Regs.DPWMPRD.all = DPWM_PERIOD;         //use .all for all values, make sure scaling matches.
		Dpwm0Regs.DPWMEV1.all = (DEAD_TIME_1)+10;              //Put event 1 at start of period
		Dpwm0Regs.DPWMEV2.all =((DPWM_PERIOD)>>5);       //1/4 of period - divide is OK because it's all constants.
		Dpwm0Regs.DPWMEV3.all = ((DPWM_PERIOD)>>5)+(DEAD_TIME_2);       //1/2 of period
		Dpwm0Regs.DPWMEV4.all = 10;
		Dpwm0Regs.DPWMSAMPTRIG1.all =2000 ;

		Dpwm0Regs.DPWMCTRL2.bit.SAMPLE_TRIG_1_EN = 1; //enable 1 sample trigger
		Dpwm0Regs.DPWMCTRL1.bit.EVENT_UP_SEL = 1; //update at end of period

		Dpwm0Regs.DPWMPHASETRIG.all=(DPWM_PERIOD)/4;

		FeCtrl0Regs.EADCCTRL.bit.AFE_GAIN = 3;// Gain X8
		FeCtrl0Regs.EADCCTRL.bit.EADC_MODE = 0;
		FeCtrl0Regs.RAMPCTRL.bit.RAMP_EN = 1;
		FeCtrl0Regs.EADCCTRL.bit.SAMP_TRIG_SCALE= 0;
		FeCtrl0Regs.EADCCTRL.bit.EADC_ENA = 1;

		LoopMuxRegs.SAMPTRIGCTRL.bit.FE0_TRIG_DPWM0_EN = 1;  // Enables Sample Trigger from DPWM 0 to Front End Control 0
		LoopMuxRegs.GLBEN.bit.DPWM0_EN=1;
		LoopMuxRegs.GLBEN.bit.FE_CTRL0_EN=1;
		Dpwm0Regs.DPWMCTRL0.bit.PWM_EN = 1;



		adc_struct.system_voltage=AdcRegs.ADCRESULT[0].all;
		adc_struct.battery_voltage=AdcRegs.ADCRESULT[1].all;
		adc_struct.battery_current=AdcRegs.ADCRESULT[2].all;
		adc_struct.system_current=AdcRegs.ADCRESULT[3].all;


	// Wait till input stabilizes

		temp=adc_struct.battery_voltage;



		if(adc_struct.battery_voltage < (dflash_variables.variables.UVP_battery) )
		{

			error_state= NO_BATTERY_CONNECTED;
			error_value=adc_struct.battery_voltage;
			while(adc_struct.battery_voltage < dflash_variables.variables.UVP_battery)
			{
				AdcRegs.ADCCTRL.bit.SW_START = 1;
				AdcRegs.ADCCTRL.bit.SW_START=0;
				pmbus_handler();
				fine_tune();
				adc_struct.system_voltage=AdcRegs.ADCRESULT[0].all;
				adc_struct.battery_voltage=AdcRegs.ADCRESULT[1].all;
			}
		}


		adc_struct.system_voltage=AdcRegs.ADCRESULT[0].all;
		adc_struct.battery_voltage=AdcRegs.ADCRESULT[1].all;
		adc_struct.battery_current=AdcRegs.ADCRESULT[2].all;
		adc_struct.system_current=AdcRegs.ADCRESULT[3].all;




		I_OUT_ZERO=0;
		FeCtrl0Regs.EADCDAC.bit.DAC_VALUE= I_OUT_ZERO;


		for(i=0;i<400000;i++)
		{
		j++;
		}

		{

		delta=(FeCtrl0Regs.EADCVALUE.bit.ERROR_VALUE)*(10.24);
		I_OUT_ZERO=	I_OUT_ZERO-delta;
		}

		FeCtrl0Regs.EADCDAC.bit.DAC_VALUE= I_OUT_ZERO;


		while(FeCtrl0Regs.EADCVALUE.bit.ERROR_VALUE !=0)
		{
			pmbus_handler();
			fine_tune();
			if( FeCtrl0Regs.EADCVALUE.bit.ERROR_VALUE <0)
			{
				FeCtrl0Regs.EADCDAC.bit.DAC_VALUE++;
			}
			else if(FeCtrl0Regs.EADCVALUE.bit.ERROR_VALUE >0)
			{
				FeCtrl0Regs.EADCDAC.bit.DAC_VALUE--;
			}
			error_state=FEED_BACK_ERROR;
		}
		I_OUT_ZERO=FeCtrl0Regs.EADCDAC.bit.DAC_VALUE;

		Dpwm0Regs.DPWMCTRL0.bit.PWM_EN = 0;
		FeCtrl0Regs.EADCCTRL.bit.EADC_ENA = 0;
		MiscAnalogRegs.GLBIOEN.bit.DPWM0A_IO_EN=0;
		MiscAnalogRegs.GLBIOEN.bit.DPWM0B_IO_EN=0;

		LoopMuxRegs.GLBEN.bit.DPWM0_EN=0;
		LoopMuxRegs.GLBEN.bit.FE_CTRL0_EN=0;
//
//		if(I_OUT_ZERO > 15000)
//		{
//			error_value=delta;
//			while(1)
//			{
//				pmbus_handler();
//				fine_tune();
//			}
//		}

	    LoopMuxRegs.SAMPTRIGCTRL.bit.FE0_TRIG_DPWM0_EN = 0;  // Enables Sample Trigger from DPWM 0 to Front End Control 0

}

