#include "ADE7953.h"

volatile uint64_t proud=0;
volatile uint32_t proud_desetiny=0;

volatile uint64_t napeti=0;
volatile uint32_t napeti_desetiny=0;

volatile int64_t active_power=0;
volatile int32_t active_power_desetiny=0;

volatile int64_t reactive_power=0;
volatile int32_t reactive_power_desetiny=0;

volatile int64_t apparent_power=0;
volatile int32_t apparent_power_desetiny=0;

volatile int64_t ucinik=0;

volatile int64_t active_energy=0;
volatile int32_t active_energy_desetiny=0;

volatile int64_t a_energy=0;

volatile int32_t active_energy_pole[6];
volatile int32_t active_power_pole[6];
volatile int32_t apparent_power_pole[6];
volatile uint32_t napeti_pole[6];
volatile uint32_t proud_pole[6];
volatile int32_t ucinik_pole[6];





volatile uint64_t proud_server=0;
volatile uint64_t napeti_server=0;
volatile int64_t active_power_server=0;
volatile int64_t apparent_power_server=0;
volatile int64_t ucinik_server=0;
volatile int64_t active_energy_server=0;







void ADE7953_write_reg_8 (uint16_t reg, uint8_t val)
{
	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_BUSY) != RESET);
	I2C_TransferHandling(ADE7953_I2C, ADE7953_ADDR, 3, I2C_AutoEnd_Mode, I2C_Generate_Start_Write);

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) ((reg>>8)&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) (reg&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, val);

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_STOPF) == RESET);
	I2C_ClearFlag(ADE7953_I2C, I2C_ICR_STOPCF);
}

void ADE7953_write_reg_16 (uint16_t reg, uint16_t val)
{
	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_BUSY) != RESET);
	I2C_TransferHandling(ADE7953_I2C, ADE7953_ADDR, 4, I2C_AutoEnd_Mode, I2C_Generate_Start_Write);

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) ((reg>>8)&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) (reg&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) ((val>>8)&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) (val&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_STOPF) == RESET);
	I2C_ClearFlag(ADE7953_I2C, I2C_ICR_STOPCF);
}

void ADE7953_write_reg_24 (uint16_t reg, uint32_t val)
{
	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_BUSY) != RESET);
	I2C_TransferHandling(ADE7953_I2C, ADE7953_ADDR, 5, I2C_AutoEnd_Mode, I2C_Generate_Start_Write);

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) ((reg>>8)&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) (reg&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) ((val>>16)&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) ((val>>8)&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) (val&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_STOPF) == RESET);
	I2C_ClearFlag(ADE7953_I2C, I2C_ICR_STOPCF);
}

void ADE7953_write_reg_32 (uint16_t reg, uint32_t val)
{
	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_BUSY) != RESET);
	I2C_TransferHandling(ADE7953_I2C, ADE7953_ADDR, 6, I2C_AutoEnd_Mode, I2C_Generate_Start_Write);

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) ((reg>>8)&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) (reg&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) ((val>>24)&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) ((val>>16)&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) ((val>>8)&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) (val&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_STOPF) == RESET);
	I2C_ClearFlag(ADE7953_I2C, I2C_ICR_STOPCF);
}

uint8_t ADE7953_read_reg_8 (uint16_t reg)
{
	uint8_t temp=0;

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_BUSY) != RESET);
	I2C_TransferHandling(ADE7953_I2C, ADE7953_ADDR, 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) ((reg>>8)&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) (reg&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TC) == RESET);
	I2C_TransferHandling(ADE7953_I2C, ADE7953_ADDR, 1, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_RXNE) == RESET);
	temp|=0xff&I2C_ReceiveData(ADE7953_I2C);

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_STOPF) == RESET);
	I2C_ClearFlag(ADE7953_I2C, I2C_ICR_STOPCF);

	return temp;
}

uint16_t ADE7953_read_reg_16 (uint16_t reg)
{
	uint16_t temp=0;

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_BUSY) != RESET);
	I2C_TransferHandling(ADE7953_I2C, ADE7953_ADDR, 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) ((reg>>8)&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) (reg&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TC) == RESET);
	I2C_TransferHandling(ADE7953_I2C, ADE7953_ADDR, 2, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_RXNE) == RESET);
	temp|=0xff&I2C_ReceiveData(ADE7953_I2C);
	temp<<=8;

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_RXNE) == RESET);
	temp|=0xff&I2C_ReceiveData(ADE7953_I2C);

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_STOPF) == RESET);
	I2C_ClearFlag(ADE7953_I2C, I2C_ICR_STOPCF);

	return temp;
}

uint32_t ADE7953_read_reg_24 (uint16_t reg)
{
	uint32_t temp=0;

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_BUSY) != RESET);
	I2C_TransferHandling(ADE7953_I2C, ADE7953_ADDR, 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) ((reg>>8)&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) (reg&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TC) == RESET);
	I2C_TransferHandling(ADE7953_I2C, ADE7953_ADDR, 3, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_RXNE) == RESET);
	temp|=0xff&I2C_ReceiveData(ADE7953_I2C);
	temp<<=8;

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_RXNE) == RESET);
	temp|=0xff&I2C_ReceiveData(ADE7953_I2C);
	temp<<=8;

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_RXNE) == RESET);
	temp|=0xff&I2C_ReceiveData(ADE7953_I2C);

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_STOPF) == RESET);
	I2C_ClearFlag(ADE7953_I2C, I2C_ICR_STOPCF);

	return temp;
}

uint32_t ADE7953_read_reg_32 (uint16_t reg)
{
	uint32_t temp=0;

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_BUSY) != RESET);
	I2C_TransferHandling(ADE7953_I2C, ADE7953_ADDR, 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) ((reg>>8)&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TXIS) == RESET);
	I2C_SendData(ADE7953_I2C, (uint8_t) (reg&0xff));

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_TC) == RESET);
	I2C_TransferHandling(ADE7953_I2C, ADE7953_ADDR, 4, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_RXNE) == RESET);
	temp|=0xff&I2C_ReceiveData(ADE7953_I2C);
	temp<<=8;

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_RXNE) == RESET);
	temp|=0xff&I2C_ReceiveData(ADE7953_I2C);
	temp<<=8;

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_RXNE) == RESET);
	temp|=0xff&I2C_ReceiveData(ADE7953_I2C);
	temp<<=8;

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_RXNE) == RESET);
	temp|=0xff&I2C_ReceiveData(ADE7953_I2C);

	while(I2C_GetFlagStatus(ADE7953_I2C, I2C_ISR_STOPF) == RESET);
	I2C_ClearFlag(ADE7953_I2C, I2C_ICR_STOPCF);

	return temp;
}

uint32_t bit24_to_32bit (uint32_t val)
{
	if(val&0x800000)val|=0xff000000;	//zaporne cislo = pridani jednicek na dvojkovy doplnek
	return val;
}

void ADE7953_meas(void)
{
	proud=0;
	proud_desetiny=0;
	napeti=0;
	napeti_desetiny=0;
	active_power=0;
	active_power_desetiny=0;
	apparent_power=0;
	apparent_power_desetiny=0;
	ucinik=0;
	active_energy=0;
	active_energy_desetiny=0;

	for(uint32_t i=0;i<5;i++)	//vyhozeni nejnizsi hodnoty
	{
		ucinik_pole[i]=ucinik_pole[i+1];
		napeti_pole[i]=napeti_pole[i+1];
		proud_pole[i]=proud_pole[i+1];
		active_power_pole[i]=active_power_pole[i+1];
		apparent_power_pole[i]=apparent_power_pole[i+1];
	}

	ucinik_pole[5]=0;
	napeti_pole[5]=0;
	proud_pole[5]=0;
	active_power_pole[5]=0;
	apparent_power_pole[5]=0;

	ucinik_pole[5]+=(int16_t) ADE7953_read_reg_16(PFA);
	napeti_pole[5]+=ADE7953_read_reg_24(VRMS);
	proud_pole[5]+=ADE7953_read_reg_24(IRMSA);
	active_power_pole[5]+=(int32_t)bit24_to_32bit(ADE7953_read_reg_24(AWATT));
	apparent_power_pole[5]+=(int32_t)bit24_to_32bit(ADE7953_read_reg_24(AVA));
	a_energy+=(int32_t)bit24_to_32bit(ADE7953_read_reg_24(AENERGYA));

	active_energy=a_energy;

	for(uint32_t i=0;i<6;i++)
	{
		napeti+=napeti_pole[i];
		proud+=proud_pole[i];
		active_power+=active_power_pole[i];
		apparent_power+=apparent_power_pole[i];
		ucinik+=ucinik_pole[i];
	}

	napeti/=6;
	proud/=6;
	active_power/=6;
	apparent_power/=6;
	ucinik/=6;

	//PF ma hodnotu -1...-32768,32767...0, potrebujeme hodnotu -0...10000...0 (hodnota je nasobena 10000)
	ucinik_server=(ucinik*10000)/32767;
	ucinik=(ucinik*10000)/32767;

	proud_server=((proud*1000)/261197);
	proud*=1000;
	proud/=261197;
	proud_desetiny=proud%1000;
	proud/=1000;

	napeti_server=((napeti*1000)/34350);
	napeti*=1000;
	napeti/=34350;
	napeti_desetiny=(napeti%1000)/100;
	napeti/=1000;

	if(active_power<50) active_power=0;
	active_power_server=((active_power*1000)/536);
	active_power*=1000;
	active_power/=536;
	active_power_desetiny=(active_power%1000)/100;
	active_power/=1000;

	if(apparent_power<50) apparent_power=0;
	apparent_power_server=((apparent_power*1000)/536);
	apparent_power*=1000;
	apparent_power/=536;
	apparent_power_desetiny=(apparent_power%1000)/100;
	apparent_power/=1000;

	if(active_energy<0) active_energy=0;
	active_energy*=100000;
	//energie/=8219953;
	active_energy/=8232138;
	active_energy_server=active_energy;
	active_energy_desetiny=active_energy%1000;
	active_energy/=1000;
}

void ADE7953_init(void)
{
	ADE7953_write_reg_8(0xFE,0xAD);
	ADE7953_write_reg_16(ADE_PERFORMANCE_REG,0x30);
	//ADE7953_write_reg_8(LCYCMODE,0);	//nemazat registry po cteni

	ADE7953_write_reg_24(AIRMSOS,(int)-768);
	ADE7953_write_reg_24(VRMSOS,(int)-768);

	//ADE7953_write_reg_16(CFMODE,0b0000000000000000);

	//ADE7953_write_reg_16(PHCALA,(54|0b0000001000000000));
	ADE7953_write_reg_16(CF1DEN,0xff);
	ADE7953_write_reg_16(CF1DEN,0xff);
}
