/*
 * DAC8563_driver.c
 *
 *  Created on: 27. 1. 2020
 *      Author: Ondrej Vitoslavsky
 */

#include "main.h"
#include "DAC8563_driver.h"


SPI_HandleTypeDef hspi2;

void DA_Init(){
	DA_LowLevel_Init();
	DA_SPI_Init();

	DA_Com_Stop();
	HAL_Delay(10);
	DA_Write(DA_REFERENCE, 0, INTERNAL_REF_ON );
	DA_Write(DA_LDAC, 0, LDAC_INACTIV );
	DA_Data_Output(DA_0mA,DA_A_B);
}

void DA_LowLevel_Init(void){
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	__HAL_RCC_GPIOB_CLK_ENABLE();
	__HAL_RCC_GPIOD_CLK_ENABLE();


	GPIO_InitStruct.Pin = DA_SPI_SCK_PIN;
	GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	GPIO_InitStruct.Alternate=DA_SPI_SCK_AF;
	HAL_GPIO_Init(DA_SPI_SCK_GPIO_PORT, &GPIO_InitStruct);

	GPIO_InitStruct.Pin = DA_SPI_MOSI_PIN;
	GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
	GPIO_InitStruct.Pull = GPIO_PULLDOWN;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	GPIO_InitStruct.Alternate=DA_SPI_MOSI_AF;
	HAL_GPIO_Init(DA_SPI_MOSI_GPIO_PORT, &GPIO_InitStruct);

	GPIO_InitStruct.Pin = DA_SYNC_0_PIN;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	HAL_GPIO_Init(DA_SYNC_0_GPIO_PORT, &GPIO_InitStruct);

	GPIO_InitStruct.Pin = DA_SYNC_1_PIN;
	HAL_GPIO_Init(DA_SYNC_1_GPIO_PORT, &GPIO_InitStruct);

	GPIO_InitStruct.Pin = DA_LDAC_Pin;
	HAL_GPIO_Init(DA_LDAC_GPIO_Port, &GPIO_InitStruct);

	DA_Com_Stop();
}

void DA_SPI_Init(void){
	__HAL_RCC_SPI2_CLK_ENABLE();

	hspi2.Instance = DA_SPI;
	hspi2.Init.Mode = SPI_MODE_MASTER;
	hspi2.Init.Direction = SPI_DIRECTION_2LINES;
	hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
	hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;
	hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
	hspi2.Init.NSS = SPI_NSS_SOFT;
	hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
	hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
	hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
	hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
	hspi2.Init.CRCPolynomial = 10;
	if (HAL_SPI_Init(&hspi2) != HAL_OK)
	{
	Error_Handler();
	}

	__HAL_SPI_ENABLE(&hspi2);
}

void DA_Write(DacCommand Command, DacAddress Address, uint16_t Data)
{
	DA_Com_Start();
	Delay_us(1);
	DA_Send_24bit(Command<<19|Address<<16|Data);
	Delay_us(1);
	DA_Com_Stop();
}

float DA_Data_Output(uint16_t Data, DacAddress Address)
{
	DA_Write(DA_WRITE_AND_UPDATE, Address, Data);
	float Output=-20.+(20.+20.)*(((float)Data-DA_N_20mA)/(DA_P_20mA-DA_N_20mA));
	return Output;
}

void DA_Com_Start(void)						//pin SYNC_0=L DAC8563 start cteni dat
{
	HAL_GPIO_WritePin(DA_SYNC_0_GPIO_PORT, DA_SYNC_0_PIN, RESET);
}

void DA_Com_Stop(void)						//pin SYNC_0=H DAC8563 stop cteni dat
{
	HAL_GPIO_WritePin(DA_SYNC_0_GPIO_PORT, DA_SYNC_0_PIN, SET);
}

void DA_Send_24bit(uint32_t Data)
{
	uint8_t data8[3]={0};
	data8[2]=Data&0xFF;
	data8[1]=(Data>>8)&0xFF;
	data8[0]=(Data>>16)&0xFF;
	HAL_SPI_Transmit(&hspi2,&data8[0],3,HAL_TIMEOUT);

}


uint16_t DA_calculate(float Data, float Range, float Nominal, AO_Type Type){
	float Output=0;
	float min=0, max=0, nom=0;

	switch(Type){
		case Deviation_Bipolar_20mA:
			min=Nominal-Range;
			nom=Nominal;
			max=Nominal+Range;
			if(Data<min) Data=min;
			if(Data>max) Data=max;
			Output=DA_N_20mA+((DA_P_20mA-DA_N_20mA)*(Data-min))/(max-min);
			if(Output<DA_N_20mA) Output=DA_N_20mA;
			if(Output>DA_P_20mA) Output=DA_P_20mA;
			break;
		case Deviation_Unipolar_0_20mA:
			min=Nominal-Range;
			nom=Nominal;
			max=Nominal+Range;
			if(Data<min) Data=min;
			if(Data>max) Data=max;
			Output=DA_0mA+((DA_P_20mA-DA_0mA)*(Data-min))/(max-min);
			if(Output<DA_0mA) Output=DA_0mA;
			if(Output>DA_P_20mA) Output=DA_P_20mA;
			break;
		case Deviation_Unipolar_4_20mA:
			min=Nominal-Range;
			nom=Nominal;
			max=Nominal+Range;
			if(Data<min) Data=min;
			if(Data>max) Data=max;
			Output=DA_P_4mA+((DA_P_20mA-DA_P_4mA)*(Data-min))/(max-min);
			if(Output<DA_P_4mA) Output=DA_P_4mA;
			if(Output>DA_P_20mA) Output=DA_P_20mA;
			break;
		case Nominal_Unipolar_0_20mA:
			min=0;
			nom=Range/2.;
			max=Range;
			if(Nominal<min) Nominal=min;
			if(Nominal>max) Nominal=max;
			Output=DA_0mA+((DA_P_20mA-DA_0mA)*(Nominal-min))/(max-min);
			if(Output<DA_0mA) Output=DA_0mA;
			if(Output>DA_P_20mA) Output=DA_P_20mA;
			break;
		case Nominal_Unipolar_4_20mA:
			min=0;
			nom=Range/2.;
			max=Range;
			if(Nominal<min) Nominal=min;
			if(Nominal>max) Nominal=max;
			Output=DA_P_4mA+((DA_P_20mA-DA_P_4mA)*(Nominal-min))/(max-min);
			if(Output<DA_P_4mA) Output=DA_P_4mA;
			if(Output>DA_P_20mA) Output=DA_P_20mA;
			break;
		default:
			UNUSED(nom);
			UNUSED(min);
			UNUSED(max);

			break;
	}
	return (uint16_t)Output;
}



