/*
 * charger_control.c
 *
 *  Created on: May 21, 2023
 *      Author: MaxMax
 */

#include "charger_control.h"
#include "main.h"

I2C_HandleTypeDef* charger_i2c;


/*** @brief Start ADC Conversion on Charger Current Channel and returns the result
 * 	@note The ADC has a PGA leading to an input range of +-6.144 in twos complement. With single ended measurements, the range is 15 bit and
 * 	Voltage = 6.144/(2^(15)-1)
 * 	@note The charger maps a voltage range of 0-5V to the output current of 0-10A
 * 	@retval ADC Conversion register value
 */
uint16_t readADCCurrent()
{
	uint8_t writeconfigreg[3] = {0x01, 0xC1, 0xE3};
	uint8_t readconfigreg[1] = {0x01};
	uint8_t readconversionreg[1] = {0x00};
	uint8_t configreg[2];
	uint8_t conversionreg[2];

	HAL_I2C_Master_Transmit(charger_i2c, CHARGER_ADC_ADR, writeconfigreg, 3, 1000);	//Set Config Register and Start conversion

	HAL_I2C_Master_Transmit(charger_i2c, CHARGER_ADC_ADR, readconfigreg, 1, 1000);	//Read Back Config Reg to check for conversion completion
	HAL_I2C_Master_Receive(charger_i2c, CHARGER_ADC_ADR, configreg, 2, 1000);
	HAL_Delay(1);//@TODO Remove if ADC Works
	HAL_I2C_Master_Transmit(charger_i2c, CHARGER_ADC_ADR, readconversionreg, 1, 1000);	//Read Result from conversion register
	HAL_I2C_Master_Receive(charger_i2c, CHARGER_ADC_ADR, conversionreg, 2, 1000);

	return (uint16_t)(conversionreg[0]<<8 | conversionreg[1]);

}

/*** @brief Start ADC Conversion on Charger Voltage Channel and returns the result
 * 	@note The ADC has a PGA leading to an input range of +-6.144 in twos complement. With single ended measurements, the range is 15 bit and
 * 	Voltage = 6.144/(2^(15)-1)
 * 	@note The charger maps a voltage range of 0-5V to the output voltage range of 0-600V
 * 	@retval ADC Conversion register value
 */

uint16_t readADCVoltage()
{
	uint8_t writeconfigreg[3] = {0x01, 0xC1, 0xE3};
	uint8_t readconfigreg[1] = {0x01};
	uint8_t readconversionreg[1] = {0x00};
	uint8_t configreg[2];
	uint8_t conversionreg[2];

	HAL_I2C_Master_Transmit(charger_i2c, CHARGER_ADC_ADR, writeconfigreg, 3, 1000);	//Set Config Register and Start conversion

	HAL_I2C_Master_Transmit(charger_i2c, CHARGER_ADC_ADR, readconfigreg, 1, 1000);	//Read Back Config Reg to check for conversion completion
	HAL_I2C_Master_Receive(charger_i2c, CHARGER_ADC_ADR, configreg, 2, 1000);
	HAL_Delay(1);//@TODO Remove if ADC Works
	HAL_I2C_Master_Transmit(charger_i2c, CHARGER_ADC_ADR, readconversionreg, 1, 1000);	//Read Result from conversion register
	HAL_I2C_Master_Receive(charger_i2c, CHARGER_ADC_ADR, conversionreg, 2, 1000);

	return (uint16_t)(conversionreg[0]<<8 | conversionreg[1]);
}

/*** @brief Initilization Routine of the charger
 * @note initially all outputs are set to 0, remote control and charger relay are deactivated
 * 	@param hi2c Handler to I2C struct for ADC and DAC communication
 */
void charger_control_init(I2C_HandleTypeDef* hi2c)
{
	charger_i2c = hi2c;

	charger_control_disable_remote();
	charger_control_disable_charger_relay();
	charger_control_setup_DACs();
	charger_control_set_current(0);
	charger_control_set_voltage(0);
}

/*** @brief Get State of voltage, current and error flags of the charger
 *	 @retval Struct Containing charger information
 */

ChargerStatusHandleTypeDef charger_control_get_state()
{
	ChargerStatusHandleTypeDef chargerstate;
	chargerstate.voltage = readADCVoltage();
	chargerstate.current = readADCCurrent();
	chargerstate.acfail = HAL_GPIO_ReadPin(Charger_AC_Fail_GPIO_Port, Charger_AC_Fail_Pin);
	chargerstate.dcfail = HAL_GPIO_ReadPin(Charger_DC_FAIL_GPIO_Port, Charger_DC_FAIL_Pin);
	chargerstate.cc_status = HAL_GPIO_ReadPin(Charger_CC_Status_GPIO_Port, Charger_CC_Status_Pin);
	chargerstate.lim_status = HAL_GPIO_ReadPin(Charger_LIM_GPIO_Port, Charger_LIM_Pin);
	chargerstate.ot_status = HAL_GPIO_ReadPin(Charger_OT_GPIO_Port, Charger_OT_Pin);
	return chargerstate;
}

void charger_control_setup_DACs()
{
	uint8_t enabledacs[2] = {0x1C, 0x02};
	HAL_I2C_Master_Transmit(charger_i2c, CURRENT_DAC_ADR, enabledacs, 2, 1000);
	HAL_I2C_Master_Transmit(charger_i2c, VOLTAGE_DAC_ADR, enabledacs, 2, 1000);
}

/*** @brief set current channel using the DAC
 * 	@param current value in 10 bit => 0-5V are equal to 0-10A so 1 bit is approx 49mA
 *
 */

void charger_control_set_current(uint32_t current)
{
	uint8_t currentlow = current & 0xFF;
	uint8_t currenthigh = ((current>>8) & 0x03) | 0x04;
	uint8_t current_dac_data[2] = {currenthigh,currentlow};
	HAL_I2C_Master_Transmit(charger_i2c, CURRENT_DAC_ADR, current_dac_data, 2, 1000);
}

/** @brief set voltage channel using the DAC
 *  @param voltage value in 10 bit => 0-5V are equal to 0-600V so 1 bit is approx. 2.93V
 *
 */

void charger_control_set_voltage(uint32_t voltage)
{
	uint8_t voltagelow = voltage & 0xFF;
	uint8_t voltagehigh = ((voltage>>8) & 0x03) | 0x04;
	uint8_t voltage_dac_data[2] = {voltagehigh,voltagelow};
	HAL_I2C_Master_Transmit(charger_i2c, VOLTAGE_DAC_ADR, voltage_dac_data, 2, 1000);
}

/**	@brief Closes the main charger Relay
 * @note The relay is also dependend on the Shutdown Circuit
 */

void charger_control_enable_charger_relay()
{
	HAL_GPIO_WritePin(Charger_Relay_GPIO_Port, Charger_Relay_Pin, GPIO_PIN_SET);
}

/**	@brief opens the main charger Relay
 * @note The relay is also dependend on the Shutdown Circuit
 */

void charger_control_disable_charger_relay()
{
	HAL_GPIO_WritePin(Charger_Relay_GPIO_Port, Charger_Relay_Pin, GPIO_PIN_RESET);
}

/**	@brief enables remote control of the charger
 * @note The relay is also dependend on the Shutdown Circuit
 */

void charger_control_enable_remote()
{
	HAL_GPIO_WritePin(Charger_Remote_Shutdown_GPIO_Port, Charger_Remote_Shutdown_Pin, GPIO_PIN_SET);
}


/**	@brief disable remote control of the charger
 * @note The relay is also dependend on the Shutdown Circuit
 */

void charger_control_disable_remote()
{
	HAL_GPIO_WritePin(Charger_Remote_Shutdown_GPIO_Port, Charger_Remote_Shutdown_Pin, GPIO_PIN_RESET);
}


