/*
 * SpotWelder.c
 *
 *  Created on: Apr 20, 2020
 *      Author: Standa
 */


#include "main.h"
#include "SpotWelder.h"
#include "measurement.h"
#include "stm32f0xx_it.h"
#include "bbb.h"


#define BANK_CAPACITANCE_MF		94
#define CHARGING_TIMEOUT_MS		3000
#define CAPVOLTTOLERANCE_MV		1000


//This array contains precalculated voltage [mV] for given energy [mJ] which is specified bz index (index 0 contains voltage required for 0mJ, index 1 contains voltage required fo 1mJ etc).
const uint16_t VoltageForEnergyPrecalculated[] = {0, 4612,6523,7989,9225,10314,11298,12203,13046,13837,14586,15298,15978,16631,17258,17864,18450,19018,19569,20106,20628,21137,21635,22121,22597,23063,23520,23968,24407,24839,25264,25682,26093,26497,26896,27288,27675,28057,28434,28806,29172,29535,29893,30247,30596,30942,31284,31622,31957,32288,32616,32940,33262,33580,33895,34208,34517,34824,35128,35430,35729,36025,36320,36611};

void sw_Init(void){

}


/*
 * Returns voltage [mV] required for discharge of specific energy [mJ] (given the capacitance defined as constant).
 * E=0.5*C*V^2; V=sqrt(2*E/C)
 */
uint16_t sw_CalcCapVoltageFromEnergy(uint8_t energy_mJ){
	return VoltageForEnergyPrecalculated[energy_mJ];
}


/*
 * Get discharge energy which is possible with given voltage.
 */
uint8_t sw_GetEnergy(uint16_t voltage_mV){
	uint32_t Result = BANK_CAPACITANCE_MF * (voltage_mV / 100 ) * ( voltage_mV / 100 ) / 200000;
	return Result;
}


/*
 * Charge the capacitor to specified voltage
 */
int8_t sw_Charge(uint16_t capVoltage_mV){
	uint32_t Timeout = GetTick() + CHARGING_TIMEOUT_MS;

	if( meas_GetVcap() <= ( capVoltage_mV + CAPVOLTTOLERANCE_MV ) ){			//If capacitor voltage is lower than neened - best situation
		LL_GPIO_SetOutputPin(CHARGE_GPIO_Port, CHARGE_Pin);						//Start charging of capacitor bank
		while (meas_GetVcap() < capVoltage_mV){									//Wait untill the charging is ready
			if(GetTick() > Timeout){											//In case of timeout
				LL_GPIO_ResetOutputPin(CHARGE_GPIO_Port, CHARGE_Pin);			//Stop charging

				if(meas_GetVcap() >= (capVoltage_mV - CAPVOLTTOLERANCE_MV)){	//And if the capacitor voltage is at least within tolerance
					return 0;													//Return OK status
				}
				else{															//But else
					return -2;													//Return timeout
				}
			}
		}
		LL_GPIO_ResetOutputPin(CHARGE_GPIO_Port, CHARGE_Pin);					//Target voltage reached, stop charging
		return 0;																//Return OK status
	}
	else{
		return -1;		//Voltage already higher
	}
}

int16_t RepT75, RepT50, RepT25, RepEDis;


void sw_ResetReport(void){
	RepT75 = -1;
	RepT50 = -1;
	RepT25 = -1;
	RepEDis = -1;
}

/*
 * Start the discharge pulse;
 * Prepares report to analyze discharge performance
 */
int8_t sw_Weld(uint8_t duration_ms){
	uint32_t Timeout = GetTick() + duration_ms;

	uint16_t Vcapstart = meas_GetVcap();
	uint16_t ECap = sw_GetEnergy(Vcapstart);

	meas_ResetConvCntr();
	LL_GPIO_SetOutputPin(WELD_GPIO_Port, WELD_Pin);
	while(GetTick() < Timeout){
		uint16_t Vcap = meas_GetVcap();

		if( (RepT75 == -1) && (Vcap < 3*Vcapstart/4) ){
			RepT75 = meas_GetConvCntr();
		}

		if( (RepT50 == -1) && (Vcap < Vcapstart/2) ){
			RepT50 = meas_GetConvCntr();
		}

		if( (RepT25 == -1) && (Vcap < Vcapstart/4) ){
			RepT25 = meas_GetConvCntr();
		}

	}
	LL_GPIO_ResetOutputPin(WELD_GPIO_Port, WELD_Pin);
	bbb_WaitSync(10);
	RepEDis = ECap - sw_GetEnergy(meas_GetVcap());
	return 0;
}


void sw_GetReport(int16_t *repT75, int16_t *repT50, int16_t *repT25, int16_t *eDis){
	if(repT75) *repT75 = RepT75;
	if(repT50) *repT50 = RepT50;
	if(repT25) *repT25 = RepT25;
	if(eDis) *eDis = RepEDis;
}
